WindowsManagerService何时启动
main函数一般为主函数,会启动进程。
SystemServer进程中,会启动WMS
public static void main(String[] args) {
new SystemServer().run();
}
WindowsManagerService功能
管理界面绘制
APP进程如何开启
特性
存在于一个单独进程中。main会开启进程。
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
Android系统的启动
点击android图标之后,会开启一个新的进程。此进程和java中的main函数进程一样。
但是这个进程之所以不会马上关闭,因为最后一句Looper.loop(),此句让android进程一直循环,所以不会启动后就关闭。
Looper.loop();
Looper.loop
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
if (me.mInLoop) {
Slog.w(TAG, "Loop again would have the queued messages be executed"
+ " before this one completed.");
}
me.mInLoop = true;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// Allow overriding a threshold with a system prop. e.g.
// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
me.mSlowDeliveryDetected = false;
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
}
其中这句,让程序一直处于循环状态。
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
Loop消息泵机制
View页面绘制体系如何表达
谁来开辟页面线程-zygote
谁来做页面表达-phoneWindow
activity指挥phoneWindow进行界面的绘制。
谁来管理界面——WindowsManagerService
管理缓存、跳转、新建界面。
谁来管理页面组织的摆放——ViewRootImpl
界面的细节谁来组织——viewGroup
UI刷新单线程
因为信息同步代价比较高,所以Android中的UI刷新采用单线程进行刷新。
如果保证页面的单线程刷新——ViewRootImpl
事件分发如何实现高速运转,且能给开发者实现事件处理
首先要去中心化
1、去中心化减少中心的处理负担。
2、利用View、ViewGroup自带的类实现去中心化。
View的绘制流程
WMS工作原理
组成
1.window:它是一个抽象类,具体实现类为 PhoneWindow,它对 View 进行管理,Window是view的容器,View是Window的具体表现内容;
2.windowManager:是一个接口类,继承自接口 ViewManager,从它的名称就知道它是用来管理 Window 的,它的实现类为 WindowManagerlimpl;
3.WMS:是窗口的管理者,它负责窗口的启动、添加和删除。另外窗口的大小和层级也是由它进行管理的
Window
Window分类
1.Application Window(应用窗口): 例如Activity,Dialog;[取值范围为1-99]
2.Sub Window(子窗口): 不能独立存在,需要依附在其他窗口,例如PopupWindow[取值范国为1000-1999]
3.System Window(系统窗口): 例如Toast、输入法窗口、系统音量条窗口、系统错误窗口等[2000-2999]
Window显示层级
Window如何创建
Activity如何创建
PhoneWindow如何来的 View结构是如何联系的
startActivity会调用到ActivityThread的startActivityNow方法
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public final Activity startActivityNow(Activity parent, String id,
Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
Activity.NonConfigurationInstances lastNonConfigurationInstances, IBinder assistToken,
IBinder shareableActivityToken) {
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.assistToken = assistToken;
r.shareableActivityToken = shareableActivityToken;
r.ident = 0;
r.intent = intent;
r.state = state;
r.parent = parent;
r.embeddedID = id;
r.activityInfo = activityInfo;
r.lastNonConfigurationInstances = lastNonConfigurationInstances;
if (localLOGV) {
ComponentName compname = intent.getComponent();
String name;
if (compname != null) {
name = compname.toShortString();
} else {
name = "(Intent " + intent + ").getComponent() returned null";
}
Slog.v(TAG, "Performing launch: action=" + intent.getAction()
+ ", comp=" + name
+ ", token=" + token);
}
// TODO(lifecycler): Can't switch to use #handleLaunchActivity() because it will try to
// call #reportSizeConfigurations(), but the server might not know anything about the
// activity if it was launched from LocalAcvitivyManager.
return performLaunchActivity(r, null /* customIntent */);
}
这个方法到
return performLaunchActivity(r, null /* customIntent */);
Activity实例化流程
1、先创建Activity实例。
2、绑定PhoneWindow对象
3、PhoneWindow需要注册到WMS中,添加到ViewGroup体系中。
performLaunchActivity
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
appContext.getAttributionSource());
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
// updatePendingActivityConfiguration() reads from mActivities to update
// ActivityClientRecord which runs in a different thread. Protect modifications to
// mActivities to avoid race.
synchronized (mResourcesManager) {
mActivities.put(r.token, r);
}
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config =
new Configuration(mConfigurationController.getCompatConfiguration());
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// Activity resources must be initialized with the same loaders as the
// application context.
appContext.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
r.assistToken, r.shareableActivityToken);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
if (r.mActivityOptions != null) {
activity.mPendingOptions = r.mActivityOptions;
r.mActivityOptions = null;
}
activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
activity.mCalled = false;
// Assigning the activity to the record before calling onCreate() allows
// ActivityThread#getActivity() lookup for the callbacks triggered from
// ActivityLifecycleCallbacks#onActivityCreated() or
// ActivityLifecycleCallback#onActivityPostCreated().
r.activity = activity;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
mLastReportedWindowingMode.put(activity.getActivityToken(),
config.windowConfiguration.getWindowingMode());
}
r.setState(ON_CREATE);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
Window
DecorView
目前此处仍然为一知半解。