Android应用与SurfaceFlinger建立连接的过程
基于Android 9.0源码分析
类图
- DecorView
- Android窗口的顶级View
- PhoneWindow
- 代表Android窗口
- WindowManagerImpl
- 应用通过该类与系统窗口管理服务通信,关联特定的窗口
- WindowManagerGlobal
- 进程全局对象,实现WindowManagerImpl与系统窗口管理服务的通信
- ViewRootImpl
- 实现了View与窗口管理之间的协议
- Choreographer
- Choreographer收到显示子系统发送的Vsync信号后,协调下一帧渲染中的动画、输入和绘制过程
- FrameDisplayEventReceiver
- 在应用内请求、接收显示事件(Vsync信号等)
- ISurfaceComposer
- 定义访问SurfaceFlinger的Binder IPC接口
- BitTube
- Socket的封装,用于进程间通信,可跨进程传递
Android应用与SurfaceFlinger建立连接的过程
Android应用在执行完Activity的onResume()后会建立与SurfaceFlinger的连接,以便接受SurfaceFlinger发送的Vsync信号,下面从ActivityThread的handleResumeActivity()开始分析。
public void handleResumeActivity(IBinder token, boolean finalStateRequest, booleanisForward,
String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
// 调用Activity的onResume的方法
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
......
if (r.window == null && !a.mFinished && willBeVisible) {
// PhoneWindow对象
r.window = r.activity.getWindow();
// DecorView对象
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
// wm为WindowManagerImpl对象
ViewManager wm = a.getWindowManager();
// 窗口布局参数
WindowManager.LayoutParams l = r.window.getAttributes();
// 设置Activity的DecorView
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
// 通常mVisibleFromClient为true
if (a.mVisibleFromClient) {
// mWindowAdded这里为false
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// 设置DecorView的LayoutParams,添加DecorView到Window
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
......
}
下面看WindowManagerImpl的addView()的实现
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
// 设置params的token
applyDefaultToken(params);
// 调用WindowManagerGlobal的addView
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
// view为DecorView
// params为DecorView关联的LayoutParams
// parentWindow为PhoneWindow
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (parentWindow != null) {
// 设置LayoutParams的token、Title和包名等
parentWindow.adjustLayoutParamsForSubWindow(wparams);
} else {
// If there's no parent, then hardware acceleration for this view is
// set from the application's hardware acceleration setting.
final Context context = view.getContext();
if (context != null
&& (context.getApplicationInfo().flags
& ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
}
synchronized (mLock) {
// Start watching for system property changes.
// 监听系统属性的改变,观察者模式
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
// 查找DecorView
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
// 创建ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);
// 设置View布局参数
view.setLayoutParams(wparams);
// DecorView/ViewRootImpl/LayoutParams添加到WindowManagerGlobal
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
// 调用ViewRootImpl的setView()
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
在ViewRootImpl的构造方法中建立与SurfaceFlinger的连接,下面看ViewRootImpl的构造方法
public ViewRootImpl(Context context, Display display) {
mContext = context;
// mWindowSession为IWindowSession.Stub.Proxy对象,单例模式
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName = context.getBasePackageName();
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
mLocation.fillInStackTrace();
mWidth = -1;
mHeight = -1;
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
mWinFrame = new Rect();
// 创建W对象,Binder服务对象
// 用于接收WindowManager发送的应用窗口感兴趣的事件
mWindow = new W(this);
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
mViewVisibility = View.GONE;
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
mAdded = false;
// 创建View.AttachInfo记录添加到窗口的View的信息
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
context);
mAccessibilityManager = AccessibilityManager.getInstance(context);
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager, mHandler);
mHighContrastTextManager = new HighContrastTextManager();
mAccessibilityManager.addHighTextContrastStateChangeListener(
mHighContrastTextManager, mHandler);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = new PhoneFallbackEventHandler(context);
// 获取Choreographer对象,在Choreographer构造函数中建立与SurfaceFlinger的连接
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
if (!sCompatibilityDone) {
sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;
sCompatibilityDone = true;
}
loadSystemProperties();
}
下面看Choreographer的getInstance()的实现
// Choreographer为ThreadLocal对象,关联的线程必须有looper
public static Choreographer getInstance() {
// 调用initialValue()创建Choreographer
return sThreadInstance.get();
}
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
if (looper == Looper.getMainLooper()) {
mMainInstance = choreographer;
}
return choreographer;
}
};
private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
mHandler = new FrameHandler(looper);
// 创建FrameDisplayEventReceiver,用于接收SurfaceFlinger发给应用的Vsync信号
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource)
: null;
mLastFrameTimeNanos = Long.MIN_VALUE;
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
// 创建CallbackQueue
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
// b/68769804: For low FPS experiments.
setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
}
mCallbackQueues是一个CallbackQueue数组,包含四个链表
- CALLBACK_INPUT
- 输入回调,当接收到Vsync信号时首先运行,如处理Move事件
- CALLBACK_ANIMATION
- 动画回调,在TRAVERSAL之前运行
- CALLBACK_TRAVERSAL
- TRAVERSAL回调,执行Measure/Layout/Draw
- CALLBACK_COMMIT
- COMMIT回调,处理帧绘制完成后的操作,如应用整理内存等
FrameDisplayEventReceiver继承自DisplayEventReceiver,下面分析它构造方法
public DisplayEventReceiver(Looper looper, int vsyncSource) {
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
// Looper关联的MessageQueue
mMessageQueue = looper.getQueue();
// Native层的DisplayEventReceiver初始化
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
vsyncSource);
// CloseGuard用于当DisplayEventReceiver被回收时,释放资源
mCloseGuard.open("dispose");
}
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj, jint vsyncSource) {
// 所在线程的MessageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 创建NativeDisplayEventReceiver,与SurfaceFlinger建立连接
// 获取显示事件socket接收端
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue, vsyncSource);
// 监听显示事件socket接收端
status_t status = receiver->initialize();
if (status) {
String8 message;
message.appendFormat("Failed to initialize display event receiver. status=%d", status);
jniThrowRuntimeException(env, message.string());
return 0;
}
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
下面看NativeDisplayEventReceiver的构造方法
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) :
// 创建DisplayEventDispatcher
DisplayEventDispatcher(messageQueue->getLooper(),
static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)),
// Java层DisplayEventReceiver弱引用的JNI全局引用保存在mReceiverWeakGlobal中
// 用于后续向Java层DisplayEventReceiver传递显示事件(Vsync/Hotplug)
mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mMessageQueue(messageQueue) {
ALOGV("receiver %p ~ Initializing display event receiver.", this);
}
// 成员子对象mReceiver为DisplayEventReceiver对象
DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource) :
mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
// sf是BpSurfaceComposer对象的强指针(对象)
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
// mEventConnection为BpDisplayEventConnection的强指针
// 为客户端创建显示事件连接,通过该连接可以请求SurfaceFlinger发送Vsync以及接收
// SurfaceFlinger发送的显示事件
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != NULL) {
// 创建BitTube
mDataChannel = std::make_unique<gui::BitTube>();
// 通过Binder IPC获取对应的Connection的socket接收端
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
createDisplayEventConnection()是一个Binder IPC,它的实现在ISurfaceComposer中。
virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSourcevsyncSource)
{
Parcel data, reply;
sp<IDisplayEventConnection> result;
// 接口描述字符串写入Parcel中
int err = data.writeInterfaceToken(
ISurfaceComposer::getInterfaceDescriptor());
if (err != NO_ERROR) {
return result;
}
// vsyncSource写入Parcel中
data.writeInt32(static_cast<int32_t>(vsyncSource));
// 请求SurfaceFlinger处理CREATE_DISPLAY_EVENT_CONNECTION
err = remote()->transact(
BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
data, &reply);
if (err != NO_ERROR) {
ALOGE("ISurfaceComposer::createDisplayEventConnection: error performing "
"transaction: %s (%d)", strerror(-err), -err);
return result;
}
// 在应用端reply.readStrongBinder()返回BpBinder的强指针
// interface_case是模板方法
// result为BpDisplayEventConnection的强指针
result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
return result;
}
下面看SurfaceFlinger处理CREATE_DISPLAY_EVENT_CONNECTION请求。
status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
......
case CREATE_DISPLAY_EVENT_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
// 为客户端创建连接
sp<IDisplayEventConnection> connection(createDisplayEventConnection(
static_cast<ISurfaceComposer::VsyncSource>(data.readInt32())));
// connection写入reply Parcel中
reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR;
}
......
}
}
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource) {
if (vsyncSource == eVsyncSourceSurfaceFlinger) {
return mSFEventThread->createEventConnection();
} else {
// 调用EventThread的createEventConnection()
return mEventThread->createEventConnection();
}
}
sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
// 创建Connection
return new Connection(const_cast<EventThread*>(this));
}
Connection是一个Binder服务类,继承自BnDisplayEventConnection,它的作用
- 处理客户端应用的Vsync请求
- 向客户端应用发送显示事件(Vsync/Hotplug)
下面看Connection的构造方法
EventThread::Connection::Connection(EventThread* eventThread)
// 创建BitTube
: count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
BitTube::BitTube(size_t bufsize) {
// 创建socket pair,用于发送显示事件
init(bufsize, bufsize);
}
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
// 设置socket buffer
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// since we don't use the "return channel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
// socket[0]用于接收端,最终通过Binder IPC返回给客户端应用
mReceiveFd.reset(sockets[0]);
// socket[1]用于发送端
mSendFd.reset(sockets[1]);
} else {
mReceiveFd.reset();
ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
}
}
BitTube的作用主要有
- 封装用于显示事件的socket通信
- 跨进程传递socket文件描述符
回到createEventConnection()方法中,由于返回Connection的强指针,在sp的构造函数中会增加强引用计数从而调用Connection的onFirstRef()方法。
void EventThread::Connection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
// 向EventThread注册连接
mEventThread->registerDisplayEventConnection(this);
}
status_t EventThread::registerDisplayEventConnection(
const sp<EventThread::Connection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
// Connection添加到mDisplayEventConnections中
mDisplayEventConnections.add(connection);
mCondition.notify_all();
return NO_ERROR;
}
Connection与EventThread采用观察者模式,当有显示事件发生时,EventThread向Connection传递事件。至此,createDisplayEventConnection()的实现就分析完了,下面看stealReceiveChannel()的实现
status_t stealReceiveChannel(gui::BitTube* outChannel) override {
// callRemote是一个模板方法,用于实现同步Binder IPC
return callRemote<decltype(
&IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
outChannel);
}
下面看Connection处理STEAL_RECEIVE_CHANNEL请求
status_t BnDisplayEventConnection::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::STEAL_RECEIVE_CHANNEL:
// 调用stealReceiveChannel处理请求
// 最终通过BitTube(outChannel)的writeToParcel将socket接收端文件描述符写入reply
return callLocal(data, reply, &IDisplayEventConnection::stealReceiveChannel);
......
}
}
status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
// 设置socket接收端文件描述符
outChannel->setReceiveFd(mChannel.moveReceiveFd());
return NO_ERROR;
}
最终,客户端应用通过BitTube的readFromParcel()获取来自SurfaceFlinger的socket文件描述符。这样客户端就可以接收SurfaceFlinger发送的显示事件了。回到nativeInit()中,继续看监听socket接收端文件描述符的过程。
status_t DisplayEventDispatcher::initialize() {
status_t result = mReceiver.initCheck();
if (result) {
ALOGW("Failed to initialize display event receiver, status=%d", result);
return result;
}
// Looper监听socket文件描述符
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
return OK;
}
DisplayEventDispatcher继承自LooperCallback,当有显示事件到来时,Looper关联的线程将调用DisplayEventDispatcher的handleEvent()处理事件。这样Android应用与SurfaceFlinger就建立了连接,可以接收SurfaceFlinger发送的显示事件了。
为了后续分析,下面继续分析ViewRootImpl的setView()
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView {
synchronized (this) {
if (mView == null) {
mView = view;
mAttachInfo.mDisplayState = mDisplay.getState();
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
attrs = mWindowAttributes;
setTag();
......
// If the application owns the surface, don't enable hardware acceleration
// 如果应用有自己的Surface,不使能硬件加速
if (mSurfaceHolder == null) {
// While this is supposed to enable only, it can effectively disable
// the acceleration too.
// 使能硬件加速,也可以禁止
enableHardwareAcceleration(attrs);
final boolean useMTRenderer = MT_RENDERER_AVAILABLE
&& mAttachInfo.mThreadedRenderer != null;
if (mUseMTRenderer != useMTRenderer) {
// Shouldn't be resizing, as it's done only in window setup,
// but end just in case.
endDragResizing();
mUseMTRenderer = useMTRenderer;
}
}
......
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
// 调度首次layout, 请求SurfaceFlinger发送Vsync
requestLayout();
......
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
// 窗口注册到WindowManagerService
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
} catch (RemoteException e) {
mAdded = false;
mView = null;
mAttachInfo.mRootView = null;
mInputChannel = null;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
attrs.restore();
}
}
......
}
}
}
下面重点分析上述方法中的以下三个过程
- 使能硬件加速的过程
- 调度首次layout的过程
- 窗口注册到WindowManagerService的过程
使能硬件加速的过程
下面从enableHardwareAcceleration()开始分析。
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
mAttachInfo.mHardwareAccelerated = false;
mAttachInfo.mHardwareAccelerationRequested = false;
// Don't enable hardware acceleration when the application is in compatibility mode
if (mTranslator != null) return;
// Try to enable hardware acceleration if requested
// 默认hardwareAccelerated为true
// 在低端设备上,Persistent进程(包括system进程)不应该使用hardwareAccelerated,因为hardwareAccelerated消耗更多的资源,比如内存
final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
if (hardwareAccelerated) {
if (!ThreadedRenderer.isAvailable()) {
return;
}
......
// 对于startingWindow,设置窗口的FLAG_HARDWARE_ACCELERATED及PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED使得绘制与应用窗口绘制相似(并非真正的hardwareAccelerated)
final boolean fakeHwAccelerated = (attrs.privateFlags &
WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0;
// 用于在system进程中,某些UI绘制强制使用hardwareAccelerated
final boolean forceHwAccelerated = (attrs.privateFlags &
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0;
if (fakeHwAccelerated) {
// This is exclusively for the preview windows the window manager
// shows for launching applications, so they will look more like
// the app being launched.
mAttachInfo.mHardwareAccelerationRequested = true;
} else if (!ThreadedRenderer.sRendererDisabled
|| (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
// 使能硬件加速
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.destroy();
}
final Rect insets = attrs.surfaceInsets;
final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
|| insets.top != 0 || insets.bottom != 0;
// 是否透明
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
final boolean wideGamut =
mContext.getResources().getConfiguration().isScreenWideColorGamut()
&& attrs.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
// 创建ThreadedRenderer
mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
attrs.getTitle().toString());
mAttachInfo.mThreadedRenderer.setWideGamut(wideGamut);
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mHardwareAccelerated =
mAttachInfo.mHardwareAccelerationRequested = true;
}
}
}
}
- ThreaderedRenderer用于将渲染工作委托给RenderThread
下面看ThreaderedRenderer的create()方法
public static ThreadedRenderer create(Context context, boolean translucent, Stringname) {
ThreadedRenderer renderer = null;
if (isAvailable()) {
// 检查是否支持Threaded rendering
// 旧版本的模拟器可能不支持
renderer = new ThreadedRenderer(context, translucent, name);
}
return renderer;
}
ThreadedRenderer(Context context, boolean translucent, String name) {
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
mAmbientShadowAlpha =
(int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
a.recycle();
// 创建Native RootRenderNode对象,rootNodePtr为对象的地址
long rootNodePtr = nCreateRootRenderNode();
// 产生一个Java RenderNode关联Native RenderNode
mRootNode = RenderNode.adopt(rootNodePtr);
mRootNode.setClipToBounds(false);
mIsOpaque = !translucent;
// 创建RenderProxy及RenderThread
mNativeProxy = nCreateProxy(translucent, rootNodePtr);
nSetName(mNativeProxy, name);
// 1) 设置RenderThread的调度信息
// 2) 请求系统GraphicsStatsService创建匿名共享内存,用于存储应用渲染信息(dumpsys gfxinfo)
ProcessInitializer.sInstance.init(context, mNativeProxy);
// 加载渲染所需的系统属性
loadSystemProperties();
}
- RenderNode
- 存储记录的画布命令,以及View/ViewGroup的显示属性
- RenderProxy
- 创建以及管理RenderThread中的CanvasContext
- RenderThread
- 真正的渲染线程
下面首先看RootRenderNode的创建,然后分析RenderProxy及RenderThread。
- 真正的渲染线程
static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
// 创建RootRenderNode
RootRenderNode* node = new RootRenderNode(env);
node->incStrong(0);
node->setName("RootRenderNode");
return reinterpret_cast<jlong>(node);
}
explicit RootRenderNode(JNIEnv* env) : RenderNode() {
// 获取调用线程关联的Looper
mLooper = Looper::getForThread();
LOG_ALWAYS_FATAL_IF(!mLooper.get(),
"Must create RootRenderNode on a thread with a looper!");
// 返回JavaVM
env->GetJavaVM(&mVm);
}
这里只是简单的创建RootRenderNode,下面看RenderProxy及RenderThread的创建。
static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
jboolean translucent, jlong rootRenderNodePtr) {
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
// 创建ContextFactoryImpl
ContextFactoryImpl factory(rootRenderNode);
// 创建RenderProxy
return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
}
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
IContextFactory* contextFactory)
// 创建启动RenderThread线程
: mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
// 匿名函数创建CanvasContext
mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
});
设置DrawFrameTask关联的RenderThread、CanvasContext、RootRenderNode
mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}
RenderThread& RenderThread::getInstance() {
// This is a pointer because otherwise __cxa_finalize
// will try to delete it like a Good Citizen but that causes us to crash
// because we don't want to delete the RenderThread normally.
static RenderThread* sInstance = new RenderThread();
gHasRenderThreadInstance = true;
return *sInstance;
}
RenderThread::RenderThread()
: ThreadBase()
, mVsyncSource(nullptr)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
, mRenderState(nullptr)
, mEglManager(nullptr)
, mVkManager(nullptr) {
Properties::load();
// 启动线程,最终执行RenderThread的threadLoop方法
start("RenderThread");
}
bool RenderThread::threadLoop() {
// 设置RenderThread的优先级
setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
if (gOnStartHook) {
gOnStartHook();
}
// 与SurfaceFlinger建立连接
// 设置EglManager、RenderState、VulkanManager等
initThreadLocals();
while (true) {
// 等待工作
waitForWork();
// 处理工作项
processQueue();
if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
drainDisplayEventQueue();
mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
mPendingRegistrationFrameCallbacks.end());
mPendingRegistrationFrameCallbacks.clear();
requestVsync();
}
if (!mFrameCallbackTaskPending && !mVsyncRequested && mFrameCallbacks.size()) {
// TODO: Clean this up. This is working around an issue where a combination
// of bad timing and slow drawing can result in dropping a stale vsync
// on the floor (correct!) but fails to schedule to listen for the
// next vsync (oops), so none of the callbacks are run.
requestVsync();
}
}
return false;
}
RenderThread启动后,RenderProxy向RenderThread发送创建CanvasContext的同步请求。下面看CanvasContext的创建。
CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
// 获取RenderPipeline类型,默认是SkiaGL
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
case RenderPipelineType::OpenGL:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
std::make_unique<OpenGLPipeline>(thread));
case RenderPipelineType::SkiaGL:
// 根据renderType创建CanvasContext
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
case RenderPipelineType::SkiaVulkan:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
default:
LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
return nullptr;
}
调度首次layout的过程
下面从requestLayout()开始分析。
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 向Looper关联的消息队列中投递SyncBarrier
// 下一次执行performTraversal时移除SyncBarrier
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 添加CALLBACK_TRAVERSAL回调,当下一帧(Vsync)到来时执行绘制
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
// 通知ThreadedRenderer下一帧很快到来
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
关于synchronization barrier(target为null的特殊消息), 一般的,消息队列中的消息为同步消息,按照时间先后进行处理。当synchronization barrier进入消息队列中,队列中的同步消息被挂起(异步消息可以处理),直到synchronization barrier从消息队列中移除。尽管postAtFrontOfQueue()可以使同步消息不被挂起,请不要滥用。
下面看Choreographer的postCallback()的实现。
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}
public void postCallbackDelayed(int callbackType,
Runnable action, Object token, long delayMillis) {
......
postCallbackDelayedInternal(callbackType, action, token, delayMillis);
}
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
......
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
// 添加到CALLBACK_TRAVERSAL类型的CallbackQueue中
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {
// 请求Vsync信号
scheduleFrameLocked(now);
} else {
......
}
}
}
下面看scheduleFrameLocked()的实现
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}
// If running on the Looper thread, then schedule the vsync immediately,
// otherwise post a message to schedule the vsync from the UI thread
// as soon as possible.
if (isRunningOnLooperThreadLocked()) {
// 立即请求Vsync
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
......
}
}
}
private void scheduleVsyncLocked() {
// 调用FrameDisplayEventReceiver的scheduleVsync()
mDisplayEventReceiver.scheduleVsync();
}
public void scheduleVsync() {
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
+ "receiver has already been disposed.");
} else {
// 当下一帧到来时请求SurfaceFlinger发送Vsync
nativeScheduleVsync(mReceiverPtr);
}
}
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
sp<NativeDisplayEventReceiver> receiver =
reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
// 调用NativeDisplayEventReceiver的scheduleVsync()
status_t status = receiver->scheduleVsync();
......
}
NativeDisplayEventReceiver继承自DisplayEventDispatcher,下面scheduleVsync()的实现
status_t DisplayEventDispatcher::scheduleVsync() {
if (!mWaitingForVsync) {
ALOGV("dispatcher %p ~ Scheduling vsync.", this);
// Drain all pending events.
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
// 如果有待处理的事件(Vsync/Hotplug),丢弃
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
}
// 调用DisplayEventReceiver的requestNextVsync(),请求SurfaceFlinger发送Vsync
status_t status = mReceiver.requestNextVsync();
if (status) {
ALOGW("Failed to request next vsync, status=%d", status);
return status;
}
mWaitingForVsync = true;
}
return OK;
}
status_t DisplayEventReceiver::requestNextVsync() {
if (mEventConnection != NULL) {
// mEventConnection是BpDisplayEventConnection的强指针
mEventConnection->requestNextVsync();
return NO_ERROR;
}
return NO_INIT;
}
requestNextVsync()是一个异步Binder IPC,它的实现在IDisplayEventConnection中,下面直接看Binder服务端Connection处理REQUEST_NEXT_VSYNC请求。
void EventThread::Connection::requestNextVsync() {
// 调用EventThread的requestNextVsync处理客户端Vsync请求
mEventThread->requestNextVsync(this);
}
void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
......
// 修改连接状态
if (connection->count < 0) {
connection->count = 0;
mCondition.notify_all();
}
}
客户端请求Vsync的过程相对简单,主要是修改Connection的状态。当EventThread收到Vsync时,根据Connection的状态决定是否向Connection发送Vsync。
使用dumpsys SurfaceFlinger命令可以查看所有Connection的状态
****chn:/ $ dumpsys SurfaceFlinger
......
VSYNC state: enabled
soft-vsync: disabled
numListeners=43,
events-delivered: 11406
0x7b3a052300: count=-1
0x7b3a052360: count=-1
0x7b3a0523c0: count=-1
0x7b3a052420: count=-1
0x7b3a0524e0: count=-1
0x7b3a052960: count=-1
0x7b3a0529c0: count=-1
......
0x7b3abfe200: count=1
......
其中,numListeners表示连接数量,count的值表示状态
- count >= 1
- 连续的Vsync请求
- count = 0
- 单次Vsync请求(还没有收到Vsync)
- count = -1
- 单次Vsync请求(已经收到Vsync)或者不请求Vsync
窗口注册到WindowManagerService的过程
下面从addToDisplay()开始分析,addToDisplay()是一个Binder IPC,对应的服务端的实现在Session中。
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
// 调用WindowManagerService的addWindow
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}
public int addWindow(Session session, IWindow client, int seq,
LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
// client为IWindow.Stub.Proxy对象
......
boolean reportNewConfig = false;
WindowState parentWindow = null;
long origId;
final int callingUid = Binder.getCallingUid();
final int type = attrs.type;
synchronized(mWindowMap) {
if (!mDisplayReady) {
throw new IllegalStateException("Display has not been initialialized");
}
// DisplayContent用于记录特定屏幕的WindowStates以及相关的内容
final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
......
// 检查应用是否有权限向特定屏幕添加窗口
if (!displayContent.hasAccess(session.mUid)
&& !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) {
Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
+ "does not have access: " + displayId + ". Aborting.");
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
......
// 检查窗口是否已经添加
// mWindowMap为IWindow IBinder(BinderProxy)到WindowState的映射
if (mWindowMap.containsKey(client.asBinder())) {
Slog.w(TAG_WM, "Window " + client + " is already added");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
......
AppWindowToken atoken = null;
final boolean hasParent = parentWindow != null;
// Use existing parent window token for child windows since they go in the same token
// as there parent window so we can apply the same policy on them.
// 对于Activity窗口,根据token(IApplicationToken.Stub)查找对应的AppWindowToken
// AppWindowToken是在之前Activity启动时创建
WindowToken token = displayContent.getWindowToken(
hasParent ? parentWindow.mAttrs.token : attrs.token);
// If this is a child window, we want to apply the same type checking rules as the
// parent window type.
final int rootType = hasParent ? parentWindow.mAttrs.type : type;
boolean addToastWindowRequiresToken = false;
......
// 创建WindowState用于描述一个窗口
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
......
// 根据窗口类型调整布局参数
mPolicy.adjustWindowParamsLw(win, win.mAttrs, hasStatusBarServicePermission);
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
// 窗口添加到系统前的检查
res = mPolicy.prepareAddWindowLw(win, attrs);
......
// 创建SurfaceSession,添加Session到WindowManagerService
win.attach();
// WindowState添加到mWindowMap
mWindowMap.put(client.asBinder(), win);
win.initAppOpsState();
......
// 窗口WindowState添加到系统
win.mToken.addWindow(win);
......
// 这里WindowState的Parent为AppWindowToken
win.getParent().assignChildLayers();
}
}
下面重点分析WindowState的attach()方法
void attach() {
if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
// 调用Session的windowAddedLocked
mSession.windowAddedLocked(mAttrs.packageName);
}
void windowAddedLocked(String packageName) {
mPackageName = packageName;
mRelayoutTag = "relayoutWindow: " + mPackageName;
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
TAG_WM, "First window added to " + this + ", creating SurfaceSession");
// SurfaceSession代表一个到SurfaceFlinger的连接
// 可以有一个或多个参与合成的Surface
mSurfaceSession = new SurfaceSession();
if (SHOW_TRANSACTIONS) Slog.i(
TAG_WM, " NEW SURFACE SESSION " + mSurfaceSession);
// Session添加到WindowManagerService的mSessions中
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
下面看SurfaceSession的构造方法。
public SurfaceSession() {
mNativeClient = nativeCreate();
}
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
// 创建SurfaceComposerClient
SurfaceComposerClient* client = new SurfaceComposerClient();
// SurfaceComposerClient继承自RefBase,增加强引用计数,会调用onFirstRef
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
// 这里rootProducer为nullptr
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
// 请求SurfaceFlinger为客户端创建连接
// conn为BpSurfaceComposerClient对象的智能指针
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
createConnection()是一个Binder IPC,下面直接看SurfaceFlinger处理CREATE_CONNECTION请求。
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
return initClient(new Client(this));
}
Client为参与合成的客户端在SurfaceFlinger侧的代表,是一个Binder服务对象,通过Binder IPC传递后,在客户端得到BpSurfaceComposerClient对象。
小结