当前位置:文档之家› Android系统Activity窗口启动过程

Android系统Activity窗口启动过程

Android系统Activity窗口启动过程
Android系统Activity窗口启动过程

在Android系统中,一个Activity对应一个应用程序窗口,任何一个Activity的启动都是

由AMS服务和应用程序进程相互配合来完成的。AMS服务统一调度系统中所有进程的

Activity启动,而每个Activity的启动过程则由其所属进程来完成。AMS服务通过

realStartActivityLocked函数来通知应用程序进程启动某个Activity:

frameworks/base/services/java/com/android/server/am/ ActivityStack.java

final boolean realStartActivityLocked(ActivityRecord r,

ProcessRecord app, boolean andResume, boolean checkConfig)

throws RemoteException { ...

//系统参数发送变化,通知Activity

if (checkConfig) {

①Configuration config =

mService.mWindowManager.updateOrientationFromAppTokens(mServi

ce.mConfiguration,r.mayFreezeScreenLocked(app) ? r.appToken :

null);

mService.updateConfigurationLocked(config, r, false, false);

}

//将进程描述符设置到启动的Activity描述符中

r.app = app;

app.waitingToKill = null;

//将启动的Activity添加到进程启动的Activity列表中

int idx = app.activities.indexOf(r);

if (idx < 0) {

app.activities.add(r);

}

mService.updateLruProcessLocked(app, true, true);

try { ...

//通知应用程序进程加载Activity ②

app.thread.scheduleLaunchActivity(new Intent(r.intent),

r.appToken,

System.identityHashCode(r), https://www.doczj.com/doc/a317700094.html,,

new Configuration(mService.mConfiguration),

https://www.doczj.com/doc/a317700094.html,pat, r.icicle, results, newIntents, !andResume,

mService.isNextTransitionForward(), profileFile, profileFd, p

AMS通过realStartActivityLocked函数来调度应用程序进程启动一个Activity,参数r

为即将启动的Activity在AMS服务中的描述符,参数app为Activity运行所在的应用程序

进程在AMS服务中的描述符。函数通过IApplicationThread代理对象

ApplicationThreadProxy通知应用程序进程启动r对应的Activity,应用程序进程完成Activity的加载等准备工作后,AMS最后启动该Activity。启动Activity的创建等工作是在应用程序进程中完成的,AMS是通过IApplicationThread接口和应用程序进程通信的。r.appToken 在AMS服务端的类型为Token,是IApplicationToken的Binder本地对象。

frameworks/base/core/java/android/app/ ActivityThread.java

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, Bundle state, List pendingResults, List pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { //将AMS 服务传过来的参数封装为ActivityClientRecord对象

ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent;

r.activityInfo = info; https://www.doczj.com/doc/a317700094.html,patInfo = compatInfo; r.state = state; r.pendingResults = pendingResults;

r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profileFile = profileName; r.profileFd = profileFd; r.autoStopProfiler = autoStopProfiler; updatePendingConfiguration(curConfig); //使用异步消息方式实现Activity的启动queueOrSendMessage(https://www.doczj.com/doc/a317700094.html,UNCH_ACTIVITY, r);}

参数token从AMS服务端经过Binder传输到应用程序进程后,变为IApplicationToken的Binder代理对象,类型为IApplicationToken.Proxy,这是因为AMS和应用程序运行在不同的进程中。

通过queueOrSendMessage函数将Binder跨进程调用转换为应用程序进程中的异步消息处理

frameworks/base/core/java/android/app/ ActivityThread.java

private class H extends Handler { public void handleMessage(Message msg)

{ switch (msg.what) { case LAUNCH_ACTIVITY: { getPackageInfoNoCheck(r.activityInfo.applicationInfo, https://www.doczj.com/doc/a317700094.html,patInfo);

LAUNCH_ACTIVITY消息在应用程序主线程消息循环中得到处理,应用程序通过

handleLaunchActivity函数来启动Activity。到此AMS服务就完成了Activity的调度任务,

将Activity的启动过程完全交给了应用程序进程来完成。

frameworks/base/core/java/android/app/ ActivityThread.java

private void handleLaunchActivity(ActivityClientRecord r, Intent

customIntent) { //主线程空闲时会定时执行垃圾回收,主线程当前要完成启动

Activity的任务,因此这里先暂停GC unscheduleGcIdler(); if

(r.profileFd != null) {

mProfiler.setProfiler(r.profileFile, r.profileFd);

mProfiler.startProfiling();

mProfiler.autoStopProfiler = r.autoStopProfiler; }

// Make sure we are running with the most recent config.

①handleConfigurationChanged(null, null); //创建Activity

②Activity a = performLaunchActivity(r, customIntent);

if (a != null) { r.createdConfig = new

Configuration(mConfiguration); Bundle oldState = r.state; //启动Ac performLaunchActivity

应用程序进程通过performLaunchActivity函数将即将要启动的Activity加载到当前进程

空间来,同时为启动Activity做准备。

frameworks/base/core/java/android/app/ ActivityThread.java

private Activity performLaunchActivity(ActivityClientRecord r, Intent

customIntent) { ActivityInfo aInfo = r.activityInfo; if

(r.packageInfo == null) { //通过Activity所在的应用程序信

息及该Activity对应的CompatibilityInfo信息从PMS服务中查询当前

Activity的包信息r.packageInfo =

getPackageInfo(aInfo.applicationInfo,

https://www.doczj.com/doc/a317700094.html,patInfo,Context.CONTEXT_INCLUDE_CODE); } //获取当前

Activity的组件信息ComponentName component =

r.intent.getComponent(); if (component == null) {

component =

r.intent.resolveActivity(mInitialApplication.getPackageManager()); r.intent ComponentName(r.activityInfo.packageName,

r.activityInfo.targetActivity); } //通过类反射方

式加载即将启动的Activity Activity activity = null; try { https://www.doczj.com/doc/a317700094.html,ng r.intent);

StrictMode.incrementExpectedActivityCount(activity.getClass()

); r.intent.setExtrasClassLoader(cl); if

(r.state != null) { r.state.setClassLoader(cl); } } mInstrumentation); if (activity != null) {

//为当前Activity创建上下文对象ContextImpl

ContextImpl appContext = new ContextImpl();

//上下文初始化③appContext.init(r.packageInfo,

r.token, this); appContext.setOuterContext(activity); C 前启动的Activity和上下文ContextImpl、Application绑定④activi https://www.doczj.com/doc/a317700094.html,stNonConfigurationInstances, config); ... / ActivityClientRecord为Activity在应用程序进程中的描述符r.activi mActivities.put(r.token, r); } catch

(SuperNotCalledException e) { ... } return

activity;}

在该函数中,首先通过PMS服务查找到即将启动的Activity的包名信息,然后通过类反射

方式创建一个该Activity实例,同时为应用程序启动的每一个Activity创建一个

LoadedApk实例对象,应用程序进程中创建的所有LoadedApk对象保存在ActivityThread

的成员变量mPackages中。接着通过LoadedApk对象的makeApplication函数,使用单例模

式创建Application对象,因此在android应用程序进程中有且只有一个Application实例。

然后为当前启动的Activity创建一个ContextImpl上下文对象,并初始化该上下文,到此

我们可以知道,启动一个Activity需要以下对象:

1) XXActivity对象,需要启动的Activity;

2) LoadedApk对象,每个启动的Activity都拥有属于自身的LoadedApk对象;

3) ContextImpl对象,每个启动的Activity都拥有属于自身的ContextImpl对

象;

4) Application对象,应用程序进程中有且只有一个实例,和Activity是一对

多的关系;

加载Activity类

public Activity newActivity(ClassLoader cl, String className,

Intent intent) throws InstantiationException,

IllegalAccessException, ClassNotFoundException {

return (Activity)cl.loadClass(className).newInstance();}

这里通过类反射的方式来加载要启动的Activity实例对象。

LoadedApk构造过程

首先介绍一下LoadedApk对象的构造过程:

frameworks/base/core/java/android/app/ ActivityThread.java

public final LoadedApk getPackageInfo(String packageName,

CompatibilityInfo compatInfo, int flags) { synchronized

(mPackages) { //通过Activity的包名从对应的成员变量中查找

LoadedApk对象WeakReference ref; if

((flags&Context.CONTEXT_INCLUDE_CODE) != 0) { ref =

mPackages.get(packageName); } else {

ref = mResourcePackages.get(packageName); } LoadedAp { ... return packageInfo; } } getPackageManager().getApplicationInfo(packageName, PackageM getPackageInfo(ai, compatInfo, flags); }return null;}

public final LoadedApk getPackageInfo(ApplicationInfo ai,

CompatibilityInfo compatInfo, int flags) { boolean

includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0; boolean securityViolation = includeCode && ai.uid != 0

&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null

((flags&(Context.CONTEXT_INCLUDE_CODE|Context.CONTEXT_IGNORE_SECURITY

)) == Context.CONTEXT_INCLUDE_CODE) {

... } return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);}

private LoadedApk getPackageInfo(ApplicationInfo aInfo,

CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode) { //再次从对应的成员变量

中查找LoadedApk实例synchronized (mPackages) {

WeakReference ref; if (includeCode) { r null; if (packageInfo == null || (packageInfo.mResources !=

null

&& !packageInfo.mResources.getAssets().isUpToDate())) { . &&

(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0); //保存Lo WeakReference(packageInfo)); } else {

frameworks/base/core/java/android/app/LoadedApk.java

public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,

CompatibilityInfo compatInfo, ActivityThread

mainThread, ClassLoader baseLoader, boolean

securityViolation, boolean includeCode) { mActivityThread =

activityThread; mApplicationInfo = aInfo; mPackageName =

aInfo.packageName; mAppDir = aInfo.sourceDir; final int myUid =

Process.myUid(); mResDir = aInfo.uid == myUid ? aInfo.sourceDir PackageManager.getDataDirForUser(UserId.getUserId(myUid), m aInfo.nativeLibraryDir; mBaseClassLoader = baseLoader;

mSecurityViolation = securityViolation; mIncludeCode =

includeCode; mCompatibilityInfo.set(compatInfo); if (mAppDir ==

null) { //为应用程序进程创建一个ContextImpl上下文

if (ActivityThread.mSystemContext == null) {

ActivityThread.mSystemContext =

ContextImpl.createSystemContext(mainThread);

ActivityThread.mSystemContext.getResources().updateConfigurat

ion( mainThread.getConfiguration(), ActivityThread.mSystemContext.getClassLoader();

mResources = ActivityThread.mSystemContext.getResources();

}}

从以上LoadedApk的构造函数可以看出,LoadedApk类记录了Activity运行所在的

ActivityThread、Activity所在的应用程序信息、Activity的包名、Activity的资源路径、

Activity的库路径、Activity的数据存储路径、类加载器和应用程序所使用的资源等信息。

Application构造过程

当Activity为应用程序进程启动的第一个Activity,因此需要构造一个Application对象

frameworks/base/core/java/android/app/LoadedApk.java

public Application makeApplication(boolean forceDefaultAppClass, Instrume 的Application类名String appClass = mApplicationInfo.className;

//如果应用程序没用重写Application,则使用Android默认的

Application类if (forceDefaultAppClass || (appClass == null)) { appClass new ContextImpl(); //初始化上下文②

appContext.init(this, null, mActivityThread); //创建

Application实例对象③app =

mActivityThread.mInstrumentation.newApplication( cl, appC (instrumentation != null) { try { //调用

Application的OnCreate函数④

instrumentation.callApplicationOnCreate(app); } catch

(Exception e) { ... } } return

app;}

在应用程序开发过程中,当我们重写了Application类后,应用程序加载运行的是我们定义

的Application类,否则就加载运行默认的Application类。从Application对象的构造过

程就可以解释为什么应用程序启动后首先执行的是Application的OnCreate函数。在实例

化Application对象时,同样创建并初始化了一个ContextImpl上下文对象。

ContextImpl构造过程

前面我们介绍了,每一个Activity拥有一个上下文对象ContextImpl,每一个Application

对象也拥有一个ContextImpl上下文对象,那么ContextImpl对象又是如何构造的呢?

frameworks/base/core/java/android/app/ ContextImpl.java

ContextImpl() { mOuterContext = this;}

ContextImpl的构造过程什么也没干,通过调用ContextImpl的init函数进行初始化

final void init(LoadedApk packageInfo,IBinder activityToken,

ActivityThread mainThread) { init(packageInfo, activityToken,

mainThread, null, null);}

final void init(LoadedApk packageInfo,IBinder activityToken,

ActivityThread mainThread, Resources container,

String basePackageName) { mPackageInfo = packageInfo;

mBasePackageName = basePackageName != null ? basePackageName :

packageInfo.mPackageName; mResources =

mPackageInfo.getResources(mainThread); i f (mResources != null &&

container != null &&

container.getCompatibilityInfo().applicationScale != m container.getCompatibilityInfo()); } mMainThread = mainThread;

mContentResolver = new ApplicationContentResolver(this,

mainThread); setActivityToken(activityToken);}

从ContextImpl的初始化函数中可以知道,ContextImpl记录了应用程序的包名信息、应用

程序的资源信息、应用程序的主线程、ContentResolver及Activity对应的

IApplicationToken.Proxy,当然对应Application对象所拥有的ContextImpl上下文就没

有对应的Token了。通过前面的分析我们可以知道各个对象之间的关系:

对象Attach过程

Activity所需要的对象都创建好了,就需要将Activity和Application对象、ContextImpl

对象绑定在一起。

frameworks/base/core/java/android/app/ Activity.java

final void attach(Context context, ActivityThread aThread,

Instrumentation instr, IBinder token, Application application,

Intent intent, ActivityInfo info, CharSequence title,

Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config) {

attach(context, aThread, instr, token, 0, application, intent,

info, title, parent, id, lastNonConfigurationInstances,

config);}

context:Activity的上下文对象,就是前面创建的ContextImpl对象;

aThread:Activity运行所在的主线程描述符ActivityThread;

instr:用于监控Activity运行状态的Instrumentation对象;

token:用于和AMS服务通信的IApplicationToken.Proxy代理对象;

application:Activity运行所在进程的Application对象;

parent:启动当前Activity的Activity;

final void attach(Context context, ActivityThread aThread,

Instrumentation instr, IBinder token, int ident,

Application application, Intent intent, ActivityInfo info, CharSequ 员变量中attachBaseContext(context); //每个Activity都拥有一

个FragmentManager,这里就是将当前Activity设置到FragmentManager中管理mFragments.attachActivity(this); //创建窗口对象①mWindow = PolicyManager.makeNewWindow(this);

mWindow.setCallback(this);

mWindow.getLayoutInflater().setPrivateFactory(this); if (info.softInputMode !=

https://www.doczj.com/doc/a317700094.html,youtParams.SOFT_INPUT_STATE_UNSPECIFIED) {

mWindow.setSoftInputMode(info.softInputMode); } if (info.uiOptions != 0) {

mWindow.setUiOptions(info.uiOptions); } //记录应用程序

的UI线程mUiThread = Thread.currentThread(); //记录应用程序

的ActivityThread对象mMainThread = aThread;mInstrumentation = instr;

mToken = token; mIdent = ident; mApplication = application;

mIntent = intent; mComponent = intent.getComponent();

mActivityInfo = info; mTitle = title; mParent = parent;

mEmbeddedID = id; mLastNonConfigurationInstances = lastNonConfigurationInstances; //为Activity所在的窗口创建窗口管理器

②mWindow.setWindowManager(null, mToken,

mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); if (mParent != null) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); mCurrentConfig = config;}

在该attach函数中主要做了以下几件事:

1) 将Activity设置到FragmentManager中;

2) 根据参数初始化Activity的成员变量;

3) 为Activity创建窗口Window对象;

4) 为Window创建窗口管理器;

到此为止应用程序进程为启动的Activity对象创建了以下不同的实例对象,它们之间的关系如下:

应用程序窗口创建过程

frameworks/base/core/java/com/android/internal/policy/ PolicyManager.java public static Window makeNewWindow(Context context) { return

sPolicy.makeNewWindow(context);}

通过Policy类的makeNewWindow函数来创建一个应用程序窗口

private static final String POLICY_IMPL_CLASS_NAME =

"com.android.internal.policy.impl.Policy";private static final IPolicy sPolicy;static { try { Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME); sPolicy =

(IPolicy)policyClass.newInstance(); } catch (ClassNotFoundException ex) { ... }}

frameworks/base/policy/src/com/android/internal/policy/impl/ Policy.java

public Window makeNewWindow(Context context) { return new PhoneWindow(context);}

应用程序窗口的创建过程其实就是构造一个PhoneWindow对象。PhoneWindow类是通过静态方式加载到应用程序进程空间的。

private static final String[] preload_classes = {

"com.android.internal.policy.impl.PhoneLayoutInflater",

"com.android.internal.policy.impl.PhoneWindow",

"com.android.internal.policy.impl.PhoneWindow$1",

"com.android.internal.policy.impl.PhoneWindow$ContextMenuCall back", "com.android.internal.policy.impl.PhoneWindow$DecorView", "com.android.internal.policy.impl.PhoneWindow$PanelFeatureSta te",

"com.android.internal.policy.impl.PhoneWindow$PanelFeatureSta

te$SavedState",};

static { for (String s : preload_classes) { try { C

PhoneWindow的构造过程

public PhoneWindow(Context context) { super(context);

mAlternativePanelStyle=getContext().getResources().getBoolean

(com.android.internal.R.bool.config_alternativePanelStyle);

mLayoutInflater = LayoutInflater.from(context);}

构造过程比较简单,只是得到布局加载服务对象。

窗口管理器创建过程

通过前面的分析我们可以知道,在Activity启动过程中,会为Activity创建一个窗口对象

PhoneWindow,应用程序有了窗口那就需要有一个窗口管理器来管理这些窗口,因此在

Activity启动过程中还会创建一个WindowManager对象。

frameworks/base/core/java/android/view/ Window.java

public void setWindowManager(WindowManager wm, IBinder appToken, String

appName, boolean hardwareAccelerated) { mAppToken =

appToken;// IApplicationToken.Proxy代理对象mAppName = appName;

//得到WindowManagerImpl实例,if (wm == null) {

wm = WindowManagerImpl.getDefault(); } //为每个启动的

Activity创建一个轻量级的窗口管理器LocalWindowManager mWindowManager =

new LocalWindowManager(wm, hardwareAccelerated);}

WindowManagerImpl为重量级的窗口管理器,应用程序进程中有且只有一个

WindowManagerImpl实例,它管理了应用程序进程中创建的所有PhoneWindow窗口。Activity

并没有直接引用WindowManagerImpl实例,Android系统为每一个启动的Activity创建了

一个轻量级的窗口管理器LocalWindowManager,每个Activity通过LocalWindowManager

来访问WindowManagerImpl,它们三者之间的关系如下图所示:

WindowManagerImpl以单例模式创建,应用程序进程中有且只有一个WindowManagerImpl实

frameworks/base/core/java/android/view/ WindowManagerImpl.java

private final static WindowManagerImpl sWindowManager = new

WindowManagerImpl();public static WindowManagerImpl getDefault() {

return sWindowManager;}

应用程序进程会为每一个Activity创建一个LocalWindowManager实例对象

frameworks/base/core/java/android/view/ Window.java

LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) {

super(wm, getCompatInfo(mContext)); mHardwareAccelerated = hardwareAccelerated ||

SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);}

frameworks/base/core/java/android/view/ WindowManagerImpl.java

CompatModeWrapper(WindowManager wm, CompatibilityInfoHolder ci) {

mWindowManager = wm instanceof CompatModeWrapper ? ((Comp Display.createCompatibleDisplay(

mWindowManager.getDefaultDisplay().getDisplayId(), ci); }

mCompatibilityInfo = ci;}

public Display getDefaultDisplay() { return new

Display(Display.DEFAULT_DISPLAY, null);}

frameworks/base/core/java/android/view/Display.java

Display(int display, CompatibilityInfoHolder compatInfo) {

synchronized (sStaticInit) { if (!sInitialized) { n display; init(display);}

构造Display对象时需要初始化该对象。

frameworks/base/core/jni/android_view_Display.cpp

static void android_view_Display_init( JNIEnv* env, jobject

clazz, jint dpy){ DisplayInfo info; if (headless) {

// initialize dummy display with reasonable values

info.pixelFormatInfo.format = 1; // RGB_8888 info.fps

= 60; info.density = 160; info.xdpi = 160; info.ydp "java/lang/IllegalArgumentException", NULL); return; } } offsets.density,info.density); env->SetFloatField(clazz, offsets.xdpi,

info.xdpi); env->SetFloatField(clazz, offsets.ydpi,

info.ydpi);}

Display的初始化过程很简单,就是通过SurfaceComposerClient请求SurfaceFlinger得

到显示屏的基本信息。

frameworks/native/libs/gui/ SurfaceComposerClient.cpp

status_t SurfaceComposerClient::getDisplayInfo(

DisplayID dpy, DisplayInfo* info){ if

(uint32_t(dpy)>=NUM_DISPLAY_MAX) return BAD_VALUE;

volatile surface_flinger_cblk_t const * cblk = get_cblk();

volatile display_cblk_t const * dcblk = cblk->displays + dpy;

info->w = dcblk->w; info->h

= dcblk->h; info->orientation = dcblk->orientation;

info->xdpi = dcblk->xdpi; info->ydpi

= dcblk->ydpi; info->fps = dcblk->fps;

info->density = dcblk->density; return

getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo));}

我们知道在SurfaceFlinger启动过程中,创建了一块匿名共享内存来保存显示屏的基本信

息,这里就是通过访问这块匿名共享内存来读取显示屏信息。到此一个Activity所需要的

窗口对象就创建完成了,在应用程序窗口的创建过程中一共创建了以下几个对象:

Activity视图对象的创建过程

在Activity的attach函数中完成应用程序窗口的创建后,通过Instrumentation回调

Activity的OnCreate函数来为当前Activity加载布局文件,进一步创建视图对象。

frameworks/base/core/java/android/app/Instrumentation.java

public void callActivityOnCreate(Activity activity, Bundle icicle) {

... activity.performCreate(icicle); ...}

frameworks/base/core/java/android/app/Activity.java

final void performCreate(Bundle icicle) { onCreate(icicle);

mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( c 我们知道在应用程序开发中,需要重写Activity的OnCreate函数:

Packages/apps/xxx/src/com/xxx/ xxxActivity.java

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(https://www.doczj.com/doc/a317700094.html,yout.main_activity); ...}

在OnCreate函数中通过setContentView来设置Activity的布局文件,就是生成该Activity

的所有视图对象。

frameworks/base/core/java/android/app/Activity.java

public void setContentView(View view, https://www.doczj.com/doc/a317700094.html,youtParams params) {

getWindow().setContentView(view, params); //初始化动作条

initActionBar();}

getWindow()函数得到前面创建的窗口对象PhoneWindow,通过PhoneWindow来设置Activity

的视图。

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java

public void setContentView(int layoutResID) { //如果窗口顶级视图对象

为空,则创建窗口视图对象if (mContentParent == null) {

installDecor(); } else {//否则只是移除该视图对象中的其他视图mContent Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onCon

PhoneWindow的成员变量mContentParent的类型为ViewGroup,是窗口内容存放的地方

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java

private void installDecor() { if (mDecor == null) { ①mDecor

= generateDecor();

mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCEN

DANTS); mDecor.setIsRootNamespace(true); if

(!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) { m generateLayout(mDecor);

mDecor.makeOptionalFitsSystemWindows(); //应用程

序窗口标题栏mTitleView =

(TextView)findViewById(com.android.internal.R.id.title);

if (mTitleView != null) { ... }

else { //应用程序窗口动作条

mActionBar = (ActionBarView)

findViewById(com.android.internal.R.id.action_bar);

if (mActionBar != null) { ... }

通过函数generateDecor()来创建一个DecorView对象

protected DecorView generateDecor() { return new

DecorView(getContext(), -1);}

接着通过generateLayout(mDecor)来创建视图对象容器mContentParent

protected ViewGroup generateLayout(DecorView decor) { //通过读取属性配置文件设置窗口风格if

(a.getBoolean(com.android.internal.R.styleable.Window_windowActionBarO verlay, false)) {

requestFeature(FEATURE_ACTION_BAR_OVERLAY); } ...

//通过读取属性配置文件设置窗口标志if

(a.getBoolean(com.android.internal.R.styleable.Window_windowFullscree n, false)) {

setFlags(FLAG_FULLSCREEN,FLAG_FULLSCREEN&(~getForcedWindowFla gs())); } ... https://www.doczj.com/doc/a317700094.html,youtParams params = getAttributes(); ... mDecor.startChanging(); //根据窗口主题风格选择不同的布局文件layoutResource ... //加载布局文件

①View in = mLayoutInflater.inflate(layoutResource, null);

//添加到DecorView中②decor.addView(in, new

https://www.doczj.com/doc/a317700094.html,youtParams(MATCH_PARENT, MATCH_PARENT)); //从窗口视图中找出窗口内容视图对象③ViewGroup contentParent =

(ViewGroup)findViewById(ID_ANDROID_CONTENT); ...

mDecor.finishChanging(); return contentParent;}

到此Activity的所有视图对象都已经创建完毕,DecorView是Activity的顶级视图,由窗

口PhoneWindow对象持有,在DecorView视图对象中添加了一个ViewGroup容器组件

contentParent,所有用户定义视图组件将被添加到该容器中。

handleResumeActivity

performLaunchActivity函数完成了两件事:

1) Activity窗口对象的创建,通过attach函数来完成;

2) Activity视图对象的创建,通过setContentView函数来完成;

这些准备工作完成后,就可以显示该Activity了,应用程序进程通过调用

handleResumeActivity函数来启动Activity的显示过程。

frameworks/base/core/java/android/app/ ActivityThread.java

final void handleResumeActivity(IBinder token, boolean clearHide,

boolean isForward) { unscheduleGcIdler(); ActivityClientRecord r; try { && !a.mFinished && willBeVisible) { //获得为当前

Activity创建的窗口PhoneWindow对象r.window =

r.activity.getWindow(); //获取为窗口创建的视图

DecorView对象View decor = r.window.getDecorView(); d

②https://www.doczj.com/doc/a317700094.html,youtParams l =

r.window.getAttributes(); //将视图对象保存到

Activity的成员变量mDecor中 a.mDecor = decor; l { l.idleScreenAvailable = false; }

器中③wm.addView(decor, l); }

r; Looper.myQueue().addIdleHandler(new Idler()); }

我们知道,在前面的performLaunchActivity函数中完成Activity的创建后,会将当前当

前创建的Activity在应用程序进程端的描述符ActivityClientRecord以键值对的形式保存

到ActivityThread的成员变量mActivities中:mActivities.put(r.token, r),r.token

就是Activity的身份证,即是IApplicationToken.Proxy代理对象,也用于与AMS通信。

上面的函数首先通过performResumeActivity从mActivities变量中取出Activity的应用

程序端描述符ActivityClientRecord,然后取出前面为Activity创建的视图对象DecorView

和窗口管理器WindowManager,最后将视图对象添加到窗口管理器中。

我们知道Activity引用的其实是轻量级的窗口管理器LocalWindowManager

frameworks/base/core/java/android/view/ Window.java

public final void addView(View view, https://www.doczj.com/doc/a317700094.html,youtParams params) { WindowMa && wp.type <= https://www.doczj.com/doc/a317700094.html,ST_SUB_WINDOW)

{ if (wp.token == null) { View

decor = peekDecorView(); if (decor != null) {

{ //根据窗口类型设置不同的标题

…if (mAppName != null) { t mContainer.mAppToken; } if ((curTitle == null ||

curTitle.length() == 0) && mAppName !=

null) { wp.setTitle(mAppName); } }

if (wp.packageName == null) { wp.packageName =

mContext.getPackageName(); } if (mHardwareAccelerated) { wp.flags

LocalWindowManager的addView函数对不同类型窗口的布局参数进行相应的设置,比如布

局参数中的token设置,如果是应用程序窗口,则设置token为W本地Binder对象。如果

不是应用程序窗口,同时当前窗口没有父窗口,则设置token为当前窗口的

IApplicationToken.Proxy代理对象,否则设置为父窗口的IApplicationToken.Proxy代理

对象。最后视图组件的添加工作交给其父类来完成。LocalWindowManager继承于

CompatModeWrapper,是WindowManagerImpl的内部类。

frameworks/base/core/java/android/view/WindowManagerImpl.java

public void addView(View view, https://www.doczj.com/doc/a317700094.html,youtParams

params) { mWindowManager.addView(view, params,

mCompatibilityInfo);}

前面我们介绍了,每一个Activity拥有一个轻量级窗口管理器,通过轻量级窗口管理器LocalWindowManager来访问重量级窗口管理器WindowManagerImpl,因此视图组件的添加过

程又转交给了WindowManagerImpl来实现。

public void addView(View view, https://www.doczj.com/doc/a317700094.html,youtParams params, CompatibilityInfoHolder cih) { addView(view, params, cih, false);}

该函数又调用WindowManagerImpl的另一个重载函数来添加视图组件

private void addView(View view, https://www.doczj.com/doc/a317700094.html,youtParams params, Compatib null; synchronized (this) { ... //从mViews中查

找当前添加的View int index = findViewLocked(view, false);

//如果已经存在,直接返回if (index >= 0) {

... return; } //尚未添int count = mViews != null ? mViews.length : 0;

for (int i=0; i

(mRoots[i].mWindow.asBinder() == wparams.token) { p 的布局参数view.setLayoutParams(wparams); if

(mViews == null) { index = 1;

mViews = new View[1]; mRoots = new

ViewRootImpl[1]; mParams = new

https://www.doczj.com/doc/a317700094.html,youtParams[1]; } else {

//动态增加mViews数组长度index =

mViews.length + 1; Object[] old = mViews; mViews = ViewRootImpl[index]; System.arraycopy(old, 0, mRoots,

0, index-1); //动态增加mParams数组长度old = mP view; mRoots[index] = root; mParams[index] = wparams;

} try { ③root.setView(view, wparams,

panelParentView); } catch (RuntimeException e) { ...

}}

到此我们知道,当应用程序向窗口管理器中添加一个视图对象时,首先会为该视图对象创建一个ViewRootImpl对象,并且将视图对象、ViewRootImpl对象、视图布局参数分别保存到窗口管理器WindowManagerImpl得mViews、mRoots、mParams数组中,如下图所示:

最后通过ViewRootImpl对象来完成视图的显示过程。

ViewRootImpl构造过程

frameworks/base/core/java/android/view/ViewRootImpl.java

public ViewRootImpl(Context context) { ... ①

getWindowSession(context.getMainLooper()); 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(); ②mWindow = new W(this);

mTargetSdkVersion =

context.getApplicationInfo().targetSdkVersion;

mInputMethodCallback = new InputMethodCallback(this);

mViewVisibility = View.GONE; mTransparentRegion = new Region(); mPreviousTransparentRegion = new Region(); mFirst = true; // true for the first time the view is added mAdded = false;

mAccessibilityManager =

AccessibilityManager.getInstance(context);

android系统开机启动流程分析

一,系统引导bootloader 加电,cpu执行bootloader程序,正常启动系统,加载boot.img【其中包含内核。还有ramdisk】 二,内核kernel bootloader加载kernel,kernel自解压,初始化,载入built-in驱动程序,完成启动。 内核启动后会创建若干内核线程,在后装入并执行程序/sbin/init/,载入init process,切换至用户空间(user-space) 内核zImage解压缩 head.S【这是ARM-Linux运行的第一个文件,这些代码是一个比较独立的代码包裹器。其作用就是解压Linux内核,并将PC指针跳到内核(vmlinux)的第一条指令】首先初始化自解压相关环境(内存等),调用decompress_kernel进行解压,解压后调用start_kernel启动内核【start_kernel是任何版本linux内核的通用初始化函数,它会初始化很多东西,输出linux版本信息,设置体系结构相关的环境,页表结构初始化,设置系 统自陷入口,初始化系统IRQ,初始化核心调度器等等】,最后调用rest_init【rest_init 会调用kernel_init启动init进程(缺省是/init)。然后执行schedule开始任务调度。这个init是由android的./system/core/init下的代码编译出来的,由此进入了android的代码】。 三,Init进程启动 【init是kernel启动的第一个进程,init启动以后,整个android系统就起来了】 init进程启动后,根据init.rc 和init. .rc脚本文件建立几个基本 服务(servicemanager zygote),然后担当property service 的功能 打开.rc文件,解析文件内容。【system/core/init/init.c】将service信息放置到service.list中【system/core/init/init_parser.c】。 建立service进程。【service_start(…) execve(…)】 在init.c中,完成以下工作 1、初始化log系统【解析/init.rc和init.%hardware%.rc文件,在两个 文件解析步骤2时执行“early-init”行动】 2、初始化设备【在/dev下创建所有设备节点,下载firmwares】 3、初始化属性服务器【在两个文件解析步骤2时执行“init”行动】

Android 开机启动流程

Android的开机流程 1. 系统引导bootloader 1) 源码:bootable/bootloader/* 2) 说明:加电后,CPU将先执行bootloader程序,此处有三种选择 a) 开机按Camera+Power启动到fastboot,即命令或SD卡烧写模式,不加载内核及文件系统,此处可以进行工厂模式的烧写 b) 开机按Home+Power启动到recovery模式,加载recovery.img,recovery.i mg包含内核,基本的文件系统,用于工程模式的烧写 c) 开机按Power,正常启动系统,加载boot.img,boot.img包含内核,基本文件系统,用于正常启动手机(以下只分析正常启动的情况) 2. 内核kernel 1) 源码:kernel/* 2) 说明:kernel由bootloader加载 3. 文件系统及应用init 1) 源码:system/core/init/* 2) 配置文件:system/rootdir/init.rc, 3) 说明:init是一个由内核启动的用户级进程,它按照init.rc中的设置执行:启动服务(这里的服务指linux底层服务,如adbd提供adb支持,vold提供SD卡挂载等),执行命令和按其中的配置语句执行相应功能 4. 重要的后台程序zygote 1)源码:frameworks/base/cmds/app_main.cpp等 2) 说明:zygote是一个在init.rc中被指定启动的服务,该服务对应的命令是/system/bin/app_process a)建立Java Runtime,建立虚拟机 b) 建立Socket接收ActivityManangerService的请求,用于Fork应用程序 c) 启动System Server 5. 系统服务system server 1)源码:frameworks/base/services/java/com/android/server/SystemServer.jav a 2) 说明:被zygote启动,通过SystemManager管理android的服务(这里的服务指frameworks/base/services下的服务,如卫星定位服务,剪切板服务等) 6. 桌面launcher 1)源码:ActivityManagerService.java为入口,packages/apps/launcher*实现 2) 说明:系统启动成功后SystemServer使用xxx.systemReady()通知各个服务,系统已经就绪,桌面程序Home就是在ActivityManagerService.systemReady()通知的过程中建立的,最终调用()启launcher 7. 解锁 1) 源码: frameworks/policies/base/phone/com/android/internal/policy/impl/*lock* 2) 说明:系统启动成功后SystemServer调用wm.systemReady()通知WindowManagerService,进而调用PhoneWindowManager,最终通过LockPatternKeyguardView显示解锁界面,跟踪代码可以看到解锁界面并不是一个Activity,这是只是向特定层上绘图,其代码了存放在特殊的位置

分析Android 开机启动慢的原因

开机启动花了40多秒,正常开机只需要28秒就能开机起来。 内核的启动我没有去分析,另一个同事分析的。我主要是分析从SystemServer启来到开机动画结束显示解锁界面的这段时间,也就是开机动画的第三个动画开始到结束这段时间,这是个比较耗时阶段,一般都在17秒左右(见过牛B的手机,只需5秒)。 SystemServer分两步执行:init1和init2。init1主要是初始化native的服务,代码在sy stem_init.cpp的system_init,初始化了SurfaceFlinger和SensorService这两个native的服务。init2启动的是java的服务,比如ActivityManagerService、WindowManagerService、PackageManagerService等,在这个过程中PackageManagerService用的时间最长,因为PackageManagerService会去扫描特定目录下的jar包和apk文件。 在开机时间需要40多秒的时,从Log上可以看到,从SurfaceFlinger初始化到动画结束,要27秒左右的时间,即从SurfaceFlinger::init的LOGI("SurfaceFlinger is starting")这句Log到void SurfaceFlinger::bootFinished()的LOGI("Boot is finished (%ld ms)", long(ns 2ms(duration)) ),需要27秒左右的时间,这显然是太长了,但到底是慢在哪了呢?应该在个中间的点,二分一下,于是想到了以启动服务前后作为分隔:是服务启动慢了,还是在服务启动后的这段时间慢?以ActivityManagerService的Slog.i(TAG, "System now ready")的这句Log为分割点,对比了一下,在从SurfaceFlinger is starting到System now read y多了7秒左右的时间,这说明SystemServer在init1和init2过程中启动慢了,通过排查,发现在init1启动的时候,花了7秒多的时间,也就是system_init的LOGI("Entered system _init()")到LOGI("System server: starting Android runtime.\n")这段时间用了7秒多,而正常情况是400毫秒便可以初始化完,通过添加Log看到,在SensorService启动时,用了比较长的时间。 不断的添加Log发现,在启动SensorService时候,关闭设备文件变慢了,每次关闭一个/dev/input/下的设备文件需要100ms左右,而SensorService有60~70次的关闭文件,大概有7s左右的时间。 调用流程是: frameworks/base/cmds/system_server/library/system_init.cpp: system_init->SensorServi ce::instantiate frameworks/native/services/sensorservice/SensorService.cpp: void SensorService::onFi rstRef()->SensorDevice& dev(SensorDevice::getInstance()) hardware/libsensors/SensorDevice.cpp: SensorDevice::SensorDevice()->sensors_open hardware/libsensors/sensors.cpp: open_sensors->sensors_poll_context_t sensors_poll_context_t执行打开每个传感器设备时,遍历/dev/input/目录下的设备文件,以匹配当前需要打开的设备,遍历文件是在 hardware/libsensors/SensorBase.cpp的openInput下实现,如果打开的设备文件不是正在打开的设备文件,会执行下面语句的else部分: if (!strcmp(name, inputName)) { strcpy(input_name, filename); break;

基于MT6752的 android 系统启动流程分析报告

基于MT6752的Android系统启动流程分析报告 1、Bootloader引导 (2) 2、Linux内核启动 (23) 3、Android系统启动 (23) 报告人: 日期:2016.09.03

对于Android整个启动过程来说,基本可以划分成三个阶段:Bootloader引导、Linux kernel启动、Android启动。但根据芯片架构和平台的不同,在启动的Bootloader阶段会有所差异。 本文以MTK的MT6752平台为例,分析一下基于该平台的Android系统启动流程。 1、Bootloader引导 1.1、Bootloader基本介绍 BootLoader是在操作系统运行之前运行的一段程序,它可以将系统的软硬件环境带到一个合适状态,为运行操作系统做好准备,目的就是引导linux操作系统及Android框架(framework)。 它的主要功能包括设置处理器和内存的频率、调试信息端口、可引导的存储设备等等。在可执行环境创建好之后,接下来把software装载到内存并执行。除了装载software,一个外部工具也能和bootloader握手(handshake),可指示设备进入不同的操作模式,比如USB下载模式和META模式。就算没有外部工具的握手,通过外部任何组合或是客户自定义按键,bootloader也能够进入这些模式。 由于不同处理器芯片厂商对arm core的封装差异比较大,所以不同的arm处理器,对于上电引导都是由特定处理器芯片厂商自己开发的程序,这个上电引导程序通常比较简单,会初始化硬件,提供下载模式等,然后才会加载通常的bootloader。 下面是几个arm平台的bootloader方案: marvell(pxa935) : bootROM + OBM + BLOB informax(im9815) : bootROM + barbox + U-boot mediatek(mt6517) : bootROM + pre-loader + U-boot broadcom(bcm2157) : bootROM + boot1/boot2 + U-boot 而对MT6752平台,MTK对bootloader引导方案又进行了调整,它将bootloader分为以下两个部分: (1) 第1部分bootloader,是MTK内部(in-house)的pre-loader,这部分依赖平台。 (2) 第2部分bootloader,是LK(little kernel的缩写,作用同常见的u-boot差不多),这部分依赖操作系统,负责引导linux操作系统和Android框架。 1.2、bootloader的工作流程 1.2.1 bootloader正常的启动流程 先来看启动流程图:

linux内核启动 Android系统启动过程详解

linux内核启动+Android系统启动过程详解 第一部分:汇编部分 Linux启动之 linux-rk3288-tchip/kernel/arch/arm/boot/compressed/ head.S分析这段代码是linux boot后执行的第一个程序,完成的主要工作是解压内核,然后跳转到相关执行地址。这部分代码在做驱动开发时不需要改动,但分析其执行流程对是理解android的第一步 开头有一段宏定义这是gnu arm汇编的宏定义。关于GUN 的汇编和其他编译器,在指令语法上有很大差别,具体可查询相关GUN汇编语法了解 另外此段代码必须不能包括重定位部分。因为这时一开始必须要立即运行的。所谓重定位,比如当编译时某个文件用到外部符号是用动态链接库的方式,那么该文件生成的目标文件将包含重定位信息,在加载时需要重定位该符号,否则执行时将因找不到地址而出错 #ifdef DEBUG//开始是调试用,主要是一些打印输出函数,不用关心 #if defined(CONFIG_DEBUG_ICEDCC)

……具体代码略 #endif 宏定义结束之后定义了一个段, .section ".start", #alloc, #execinstr 这个段的段名是 .start,#alloc表示Section contains allocated data, #execinstr表示Section contains executable instructions. 生成最终映像时,这段代码会放在最开头 .align start: .type start,#function /*.type指定start这个符号是函数类型*/ .rept 8 mov r0, r0 //将此命令重复8次,相当于nop,这里是为中断向量保存空间 .endr b 1f .word 0x016f2818 @ Magic numbers to help the loader

安卓开机动画以及制作(课程设计)

洛阳理工学院 课程设计报告 课程名称嵌入式系统课程设计 设计题目 Android开机动画及声音制作专业 班级 学号 姓名 完成日期 2017年月日

课程设计任务书 设计题目:Android开机动画与声音制作 设计内容与要求: 修改Android开机动画和声音的是建立自定义Android系统的入门课程和基本功。Android系统的开机动画需要修改和设定bootanimation.zip文件,修改开机声音需要自定义OGG文件并导入系统指定位置。 题目的基本要求如下: 1. 寻找并下载合适的开机视频; 2. 将视频转换成连续的PNG图像文件; 3. 修改desc.txt文件并打包bootanimation.zip文件; 4. 获取合适的开机声音并利用格式工厂工具转换为OGG格式; 5. 通过adb shell指令,进入控制板系统内并修改android系统文件只读属性; 6. 点击开发板的“复位”进行复位,重启开发板查看修改结果。 指导教师: 年6月日 课程设计评语 成绩: 指导教师:_______________ 年月日

目录 第1章概述 (2) 1.1 Android应用平台简介 (2) 1.2 RK2928开发板介绍 (2) 第2章 Android开机动画及声音制作 (5) 2.1 基本操作流程 (5) 2.2 开机动画的制作与添加 (6) 2.3 开机声音的制作与添加 (11) 2.4 开机动画及声音结果 (12) 第3章心得体会 (13)

第1章概述 1.1 Android应用平台简介 Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成。Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。2013年的第四季度,Android平台手机的全球市场份额已经达到78.1%。 1.2 RK2928开发板介绍 图1-1 实验板外观 作为RK292系列里较为高级的芯片之一,RK2928提供了比较不错的性能。较RK2926,RK2928集成了HDMI 1.4a控制器及GPS基带的支持,为300元价

Android开机启动流程样本

Android的开机流程 1. 系统引导bootloader 1) 源码: bootable/bootloader/* 2) 说明: 加电后, CPU将先执行bootloader程序, 此处有三种选择 a) 开机按Camera+Power启动到fastboot, 即命令或SD卡烧写模式, 不加载内核及文件系统, 此处能够进行工厂模式的烧写 b) 开机按Home+Power启动到recovery模式, 加载recovery.img, recovery.img包含内核, 基本的文件系统, 用于工程模式的烧写 c) 开机按Power, 正常启动系统, 加载boot.img, boot.img包含内核, 基本文件系统, 用于正常启动手机( 以下只分析正常启动的情况) 2. 内核kernel 1) 源码: kernel/* 2) 说明: kernel由bootloader加载 3. 文件系统及应用init 1) 源码: system/core/init/* 2) 配置文件: system/rootdir/init.rc, 3) 说明: init是一个由内核启动的用户级进程, 它按照init.rc中的设置执行: 启动服务( 这里的服务指linux底层服务, 如adbd提供adb支持, vold提供SD卡挂载等) , 执行命令和按其中的配置语句执行相应功能 4. 重要的后台程序zygote 1) 源码: frameworks/base/cmds/app_main.cpp等 2) 说明: zygote是一个在init.rc中被指定启动的服务, 该服务对应的命令是/system/bin/app_process

Android系统启动过程详解

Android系统启动过程详解 Android系统启动过程 首先Android框架架构图:(来自网上,我觉得这张图看起来很清晰) Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。 启动的过程如下图所示:(图片来自网上,后面有地址)

下面将从Android4.0源码中,和网络达人对此的总结中,对此过程加以学习了解和总结, 以下学习过程中代码片段中均有省略不完整,请参照源码。

一Init进程的启动 init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行, 并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程。 启动过程就是代码init.c中main函数执行过程:system\core\init\init. c 在函数中执行了:文件夹建立,挂载,rc文件解析,属性设置,启动服务,执行动作,socket监听…… 下面看两个重要的过程:rc文件解析和服务启动。 1 rc文件解析 .rc文件是Android使用的初始化脚本文件(System/Core/Init/readm e.txt中有描述: four broad classes of statements which are Actions, Commands, Services, and Options.) 其中Command 就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是linux 命令, 还有一些是android 添加的,如:class_start :启动服务,class_stop :关闭服务,等等。 其中Options是针对Service 的选项的。 系统初始化要触发的动作和要启动的服务及其各自属性都在rc脚本文件中定义。具体看一下启动脚本:\system\core\rootdir\init.rc 在解析rc脚本文件时,将相应的类型放入各自的List中: \system\core\init\Init_parser.c :init_parse_config_file( )存入到 action_queue、action_list、service_list中,解析过程可以看一下parse_config函数,类似状态机形式挺有意思。 这其中包含了服务:adbd、servicemanager、vold、ril-daemon、deb uggerd、surfaceflinger、zygote、media…… 2 服务启动 文件解析完成之后将service放入到service_list中。 文件解析完成之后将service放入到service_list中。 \system\core\init\builtins.c

Android SystemBar启动流程分析

Android SystemBar启动流程分析 SystemBars的服务被start时,最终会调用该类的onNoService()方法。 @Override public void start() { if (DEBUG) Log.d(TAG, "start"); ServiceMonitor mServiceMonitor = new ServiceMonitor(TAG, DEBUG, mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); mServiceMonitor.start(); // will call onNoService if no remote service is found } @Override public void onNoService() { if (DEBUG) Log.d(TAG, "onNoService"); createStatusBarFromConfig(); // fallback to using an in-process implementation } private void createStatusBarFromConfig() { … mStatusBar = (BaseStatusBar) cls.newInstance(); … mStatusBar.start(); } BaseStatusBar是一个抽象类,故调用其子类的PhoneStatusBar的start 函数。 @Override public void start() { … super.start(); … } 子类的start又调用了父类的start public void start() { … createAndAddWindows(); … }

AndroidL系统启动及加载流程分析

Android L系统启动及加载流程分析 1、概述 Android L的启动可以分为几个步骤:Linux内核启动、init进程启动、native系统服务及java系统服务启动、Home启动,主要过程如下图: 图1 整个启动流程跟4.4及之前的版本相差不多,只是有个别不同之处,本文我们主要分析Linux内核启动之后的过程。

2、启动过程分析 2.1 init进程启动 当系统内核加载完成之后,会启动init守护进程,它是内核启动的第一个用户级进程,是Android的一个进程,进程号为1,init进程启动后执行入口函数main(),主要操作为: 图2 AndroidL上将selinux的安全等级提高了,设为了enforcing模式,4.4上是permissive模式。 解析rc脚本文件,即init.rc脚本,该文件是Android初始化脚本,定义了一系列的动作和执行这些动作的时间阶段e aryl-init、init、early-boot、boot、post-fs等阶段。init进程main 函数中会根据这些阶段进行解析执行。AndroidL上为了流程更清晰,增加了charger(充电开机)、ffbm(工厂模式)、以及late-init阶段,实际上这些阶段是对其他阶段的组合执行,比如late-init:

2.2 ServiceManager的启动 servicemanager的启动就是init进程通过init.rc脚本启动的: 源码在frameworks/native/cmds/servicemanager/service_manager.c中,servicemanager是服务管理器,它本身也是一个服务(handle=0),通过binder调用,为native和Java系统服务提供注册和查询服务的,即某个服务启动后,需要将自己注册到servicemanager中,供其他服务或者应用查询使用。AndroidL上servicemanger中在处理注册和查询动作之前添加了selinux安全检测相关的处理。 2.3 SurfaceFinger、MediaServer进程启动 Android4.4以前,surfacefinger的启动根据属性system_init.startsurfaceflinger,决定是通过init.rc启动还是systemserver进程启动,之后的版本包括AndoridL都是通过init.rc启动的: 启动后会向servicemanager进程注册服务中,该服务启动时主要功能是初始化整个显

android开机启动流程简单分析

android开机启动流程简单分析 android启动 当引导程序启动Linux内核后,会加载各种驱动和数据结构,当有了驱动以后,开始启动Android系统同时会加载用户级别的第一个进程init(system\core\init\init.cpp)代码如下: int main(int argc, char** argv) { ..... //创建文件夹,挂载 // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. if (is_first_stage) { mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); #define MAKE_STR(x) __STRING(x) mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); mount("sysfs", "/sys", "sysfs", 0, NULL); } ..... //打印日志,设置log的级别 klog_init(); klog_set_level(KLOG_NOTICE_LEVEL); ..... Parser& parser = Parser::GetInstance(); parser.AddSectionParser("service",std::make_unique()); parser.AddSectionParser("on", std::make_unique()); parser.AddSectionParser("import", std::make_unique()); // 加载init.rc配置文件 parser.ParseConfig("/init.rc"); } 加载init.rc文件,会启动一个Zygote进程,此进程是Android系统的一个母进程,用来启动Android的其他服务进程,代码: 从Android L开始,在/system/core/rootdir 目录中有4 个zygote 相关的启动脚本如下图:

Android ninja 编译启动过程分析

Android ninja编译启动过程分析 ---make是如何转换到到ninja编译的 1.首先你的得对make的工作机制有个大概的了解: 运行的命令在要编译的目录下运行make,或者make target_name a.分析处理保存阶段(没有实际编译动作):它首先对当前目录下的Makefile文件的做一次扫描,语法分析,还有处理,主要是变量的保存,目标依赖列表生成,目标下的action列表的生成,然后记住 b.然后按记住的目标执行action列表动作(有实际编译动作). 编译启动的入口方式还是运行make: 2开始make-jxxx方式进入.....(xxx是本机cpu的数量) make开始做进行第一次扫描.... 目前USE_NINJA还是没有定义,估计以后很久很久才能启用的了! BUILDING_WITH_NINJA开始也是没定义的 看make扫描入口文件: Makefile: include build/core/main.mk 在build/core/main.mk: 在ninia之前都有include help.mk和config.mk 97include$(BUILD_SYSTEM)/help.mk 98 99#Set up various standard variables based on configuration 100#and host information. 101include$(BUILD_SYSTEM)/config.mk 说明make help//显示make帮助make config//当前显示配置 103relaunch_with_ninja:= 104ifneq($(USE_NINJA),false) 105ifndef BUILDING_WITH_NINJA<==第二次扫描不会到这里了 106relaunch_with_ninja:=true 107endif 108endif 116ifeq($(relaunch_with_ninja),true)<===第一次扫描入这里了 117#Mark this is a ninja build. 118$(shell mkdir-p$(OUT_DIR)&&touch$(OUT_DIR)/ninja_build) 119include build/core/ninja.mk//---进入ninja.mk 第一次扫描到此为止就结束掉了,因为在当前ifeq else endif后面没有代码了 120else#///!relaunch_with_ninja<===第二次扫描入这里了

android开机过程

一、Android开机启动流程简介 1、OS-level: 由bootloader载入linux kernel后kernel开始初始化, 并载入built-in 的驱动程序。Kernel完成开机后,载入init process,切换至user-space。 Init进程是第一个在user-space启动的进程。 2、Android-level: 由init process读取init.rc,Native 服务启动,并启动重要的外部程序,例如:servicemanager、Zygote以及System Server等。 由 init process 根据硬件类型读取init.xxx.rc。由init.xxx.rc加载init.xxx.sh。 由 init.xxx.sh 加载特定的硬件驱动。如hi_tuner.ko、hi_demux.ko等。 3、Zygote-Mode: Zygote 启动完SystemServer 后,进入Zygote Mode,在Socket 等候命令。 随后,使用者将看到一个桌面环境(Home Screen)。桌面环境由一个名为[Launcher]的应用程序负责提供。 本文档重点研究Android-level中的启动流程。 启动流程如下图所示:

二、init process流程分析 init进程简介 init进程是第一个在user-space启动的进程。由内核启动参数[init]传递给内核,如果该项没有设置,内核会按 /etc/init,/bin/init,/sbin/init,/bin/sh的顺序进行尝试,如果都有的都没找到,内核会抛出 kernel panic:的错误。

Android系统启动升级流程

A n d r o i d系统启动升级 流程 TTA standardization office【TTA 5AB- TTAK 08- TTA 2C】

摘要 本文首先介绍了Android系统更新要用到的一些概念:硬件、三种模式及相互之间的通信。然后介绍了Android系统的启动和升级流程。 概述 通常,Android系统的升级包名称为update.zip。Android系统内部自带了烧写升级包的工具,我们可以手动烧写,也可以通过某些机制自动更新系统。同时,我们可以手动修改和制作升级包。本文主要阐述在Android系统升级中用到的一些概念,本文只是作为索引,并不涉及到具体的烧写工作。本文基于Android系统的版本:4.0.4。 硬件 Android系统的烧写,是非常贴近硬件的。一是,烧写是在实实在在的硬件上操作的。二则,有时在翻阅源码的时候,需要知道硬件的类型,以便找到和硬件相对应的源码。 烧写相关的硬件主要有三部分:CPU、内存和nand flash。当然,只是相对本文而言。CPU用来执行程序中的指令。内存只是在运行中,将需要运行的程序加载其中并运行,关机后即消失。nandflash用来存储程序的数据,它会一直存在。系统启动时,会将nand flash上的操作系统加载到内存,然后运行在CPU 中,对于非系统程序,按需加载到内存中运行。了解这些,有助于了解整个烧写的过程。 在板子上,可以通过下面的命令,查看CPU的信息: [plain] cat /proc/cpuinfo 通过如下命令查看内存的信息: [plain] cat /proc/meminfo nand flash是需要分区的,每个分区中对应了Android系统烧写包中不同的image,比如:boot、system分区等。可以通过如下命令来查看nand flash 的分区情况: [plain] cat /proc/mtd # 查看分区状况 通常,nand flash包含了以下分区: 开机动画:用于在开机或者升级过程中显示在屏幕上的内容。 boot:用于Android系统的正常启动 recovery:用于Android系统进入recovery模式下,参见本文后续介绍。 misc:用于保存BCB的内容,参见本文后续介绍。

Android系统的开机画面显示过程分析

Android系统的开机画面显示过程分析 分类:Android2012-07-0900:561252人阅读评论(39)收藏举报 好几个月都没有更新过博客了,从今天开始,老罗将尝试对Android系统的UI实现作一个系统的分析,也算是落实之前所作出的承诺。提到Android系统的UI,我们最先接触到的便是系统在启动过程中所出现的画面了。Android系统在启动的过程中,最多可以出现三个画面,每一个画面都用来描述一个不同的启动阶段。本文将详细分析这三个开机画面的显示过程,以便可以开启我们对Android系统UI实现的分析之路。 第一个开机画面是在内核启动的过程中出现的,它是一个静态的画面。第二个开机画面是在init进程启动的过程中出现的,它也是一个静态的画面。第三个开机画面是在系统服务启动的过程中出现的,它是一个动态的画面。无论是哪一个画面,它们都是在一个称为帧缓冲区(frame buffer,简称fb)的硬件设备上进行渲染的。接下来,我们就分别分析这三个画面是如何在fb上显示的。 1.第一个开机画面的显示过程 Android系统的第一个开机画面其实是Linux内核的启动画面。在默认情况下,这个画面是不会出现的,除非我们在编译内核的时候,启用以下两个编译选项: CONFIG_FRAMEBUFFER_CONSOLE CONFIG_LOGO 第一个编译选项表示内核支持帧缓冲区控制台,它对应的配置菜单项为:Device Drivers--->Graphics support--->Console display driver support--->Framebuffer Console support。第二个编译选项表示内核在启动的过程中,需要显示LOGO,它对应的配置菜单项为:Device Drivers--->Graphics support--->Bootup logo。配置Android 内核编译选项可以参考在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)一文。 帧缓冲区硬件设备在内核中有一个对应的驱动程序模块fbmem,它实现在文件kernel/goldfish/drivers/video/fbmem.c中,它的初始化函数如下所示: 1/**

Android应用程序内部启动Activity过程(startActivity)的源代码分析

上文介绍了Android应用程序的启动过程,即应用程序默认Activity的启动过程,一般来说,这种默认Activity是在新的进程和任务中启动的;本文将继续分析在应用程序内部启动非默认Activity的过程的源代码,这种非默认Activity一般是在原来的进程和任务中启动的。 这里,我们像上一篇文章Android应用程序启动过程源代码分析一样,采用再上一篇文章Android 应用程序的Activity启动过程简要介绍和学习计划所举的例子来分析在应用程序内部启动非默认Activity的过程。 在应用程序内部启动非默认Activity的过程与在应用程序启动器Launcher中启动另外一个应用程序的默认Activity的过程大体上一致的,因此,这里不会像上文Android应用程序启动过程源代码分析一样详细分析每一个步骤,我们着重关注有差别的地方。 回忆一下Android应用程序的Activity启动过程简要介绍和学习计划一文所用的应用程序Activity,它包含两个Activity,分别是MainActivity和SubActivity,前者是应用程序的默认Activity,后者是非默认Activity。MainActivity启动起来,通过点击它界面上的按钮,便可以在应用程序内部启动SubActivity。 我们先来看一下应用程序的配置文件AndroidManifest.xml,看看这两个Activity是如何配置的:view plain 1. 2. 6. 7. 9. 10. 11. 12. 13. 14. 16. 17. 18. 19. 20. 21. 22.

Android系统完整的启动过程

Android系统完整的启动过程,从系统层次角度可分为Linux系统层、Android系统服务层、Zygote进程模型三个阶段;从开机到启动Home Launcher完成具体的任务细节可分为七个步骤,下面就从具体的细节来解读Android系统完整的初始化过程。 一、启动BootLoader Android 系统是基于Linux操作系统的,所以它最初的启动过程和Linux一样。当设备通电后首先执行BootLoader引导装载器,BootLoader是在操作系统内核运行之前运行的一段小程序。通过这段小程序初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境引导进入合适的状态,以便为最终调用操作系统内核准备好正确的运行环境。 而Linux系统启动时: 1)首先要加载BIOS的硬件信息,并获取第一个启动设备的代号 2)读取第一个启动设备的MBR的引导加载程序(lilo、grub等)的启动信息。 3)加载核心操作系统的核心信息,核心开始解压缩,并且尝试驱动所有的硬件设备。 ………… 在嵌入式系统中,通常不会有像BIOS那样的固件程序,因此整个系统的加载任务都是通过BootLoader完成的。 二、加载系统内核 Linux内核映像通常包括两部分代码,分别为实模式代码和保护模式代码。当BootLoader装载内核映像到代码段内存时,分别放置实模式代码和保护模式代码到不同的位置,然后进入实模式代码执行,实模式代码执行完成后转入保护模式代码。 实模式和保护模式的概念再次不做过多解释,读者可以自行查阅资料。 三、启动Init进程 当系统内核加载完成之后,会首先启动Init守护进程,它是内核启动的第一个用户级进程,它的进程号总是1。Init进程启动完成之后,还负责启动其他的一些重要守护进程,包括: Usbd进程(USB Daemon):USB连接后台进程,负责管理USB连接。 adbd 进程(Android Debug Bridge Daemon):ADB连接后台进程,负责管理ADB连接。 debuggerd 进程(Debugger Daemon) :调试器后台进程,负责管理调试请求及调试过程。 rild进程(Radio Interface Layer Daemon):无线接口层后台进程,负责管理无线通信服务。 四、启动Zygote进程 Init进程和一些重要的守护进程启动完成之后,系统启动Zygote 进程。Zygote 进程启动后,首先初始化一个Dalvik VM实例,然后为它加载资源与系统共享库,并开启Socket监听服务,当收到创建Dalvik VM实例请求时,会通过COW(copy on write)技术最大程度地复用自己,生成一个新的Dalvik VM实例。Dalvik VM实例的创建方法基于linux系统的fork原理。

相关主题
文本预览
相关文档 最新文档