1. Window adding process
1.1 start from the source
To add a small floating window, you need to use addView of WindowManager,
And we checked the official documents and found that WindowManager is an interface
public interface WindowManager implements ViewManager
Its real implementation is WindowManagerImpl, which has the following code
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
1.2 explore WindowManagerGlobal
As you can see, all the operations to implement Window are handed over to WindowManagerGlobal,
It provides its own instance in the form of factory. addView mainly performs the following work:
1.2.1 check the validity of parameters and adjust parameters
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) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
}
1.2.2 create the ViewRootImpl and add the View to the list
First, focus on several parameters in WindowManagerGlobal
private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
private final ArraySet<View> mDyingViews = new ArraySet<View>();
Where mView stores the View corresponding to all windows, mRoot stores the ViewRootImpl corresponding to all windows, mParams stores the layout parameters corresponding to all windows, mDyingViews stores the View object being deleted, or the Window that has called removeView but the deletion operation has not been completed.
In addView, add a series of Window objects to the list by the following methods:
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
1.2.3 update the interface and complete the Window adding process through ViewRootImpl
First, through the setView method of ViewRootImpl:
setView Pass through requestLayout Complete asynchronous refresh:
@Override public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true; scheduleTraversals(); } }
Where scheduleTraversals is actually the entry point for View rendering.
Next,
final IWindowSession mWindowSession;
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, 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);
}
Here mWindowSession type is IWindowSession, which is a Binder object. The real implementation class is Session.
That is to say, Window adding is an IPC call.
The internal Session will add windows through WindowManagerService.
It's not over. I'll write it tomorrow