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
对象。