android AMS 详解一

文章出处:https://blog.csdn.net/shift_wwx/article/details/45742179

前言:之前 android SystemServer详解分析了一下systemserver的启动过程,虽然分析下来很多繁琐,可是systemserver却是android启动的第一步,很多service都是在这个进程中启动,这些才是组成android的关键,AMS可以说是android应用的最关键的一个service,传说中的android四大组件就是用它来控制的。我根据源码做一些分析,不足应该很多,希望大神能多指点。

AMS最开始涉及到是在systemserver中:

context = ActivityManagerService.main(factoryTest);
    public static final Context main(int factoryTest) {
        AThread thr = new AThread();//创建一个Looper,实例化AMS
        thr.start();

        synchronized (thr) {
            while (thr.mService == null) {//等待AMS实例化完成
                try {
                    thr.wait();
                } catch (InterruptedException e) {
                }
            }
        }

        ActivityManagerService m = thr.mService;//mSelf就是实例化的AMS
        mSelf = m;
        ActivityThread at = ActivityThread.systemMain();//实例化ActivityThread
        mSystemThread = at;
        Context context = at.getSystemContext();
        context.setTheme(android.R.style.Theme_Holo);
        m.mContext = context;
        m.mFactoryTest = factoryTest;
        m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());

        m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper);//activity堆栈管理类

        m.mBatteryStatsService.publish(context);
        m.mUsageStatsService.publish(context);
        m.mAppOpsService.publish(context);

        synchronized (thr) {//mSelf初始化成功后,就可以让AThread中Looper loop起来
            thr.mReady = true;
            thr.notifyAll();
        }

        m.startRunning(null, null, null, null);//调用startRuuning

        return context;
    }

注意code中的注释。

1)AThread

    static class AThread extends Thread {
        ActivityManagerService mService;
        Looper mLooper;
        boolean mReady = false;

        public AThread() {
            super("ActivityManager");
        }

        @Override
        public void run() {
            Looper.prepare();

            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);

            ActivityManagerService m = new ActivityManagerService();

            synchronized (this) {
                mService = m;
                mLooper = Looper.myLooper();
                Watchdog.getInstance().addThread(new Handler(mLooper), getName());
                notifyAll();
            }

            synchronized (this) {
                while (!mReady) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }

            // For debug builds, log event loop stalls to dropbox for analysis.
            if (StrictMode.conditionallyEnableDebugLogging()) {
                Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
            }

            Looper.loop();
        }
    }

这个是AMS中的static class,为AMS创建了一个thread,区别去system_server进程的main thread,然后为AMS创建一个Looper,然后调用Looper.loop(); 另一个目的是实例化一个AMS。

private ActivityManagerService() {
        Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());

        mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false);
        mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true);
        mBroadcastQueues[0] = mFgBroadcastQueue;
        mBroadcastQueues[1] = mBgBroadcastQueue;

        mServices = new ActiveServices(this);
        mProviderMap = new ProviderMap(this);

        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        systemDir.mkdirs();
        
        ......

}

构造函数就不详细的列出来,可以看一下AMS.java的source code。

一些变量需要注意,mBroadcastQueues(mFgBroadcastQueue、mBgBroadcastQueue)、mServices、mProviderMap四大组件三个在这里出现了,另外一个后期介绍。另外还有其他变量,mBatteryStatsService、mProcessStats、mUsageStatsService、mAppOpsService、mGrantFile、mStartedUsers、mCompatModePackages、mProcessCpuThread等等。

从code看,是在/data/system/下,创建了一些文件来管理android系统一些状态,例如batterystats.bin就是电池状态,接着procstats管理进程的,appops.xml就是app 权限相关的等等,后期会做详细的分析。

2)通过上面分析AThread后mSelf = m;

mSelf是static类型的,下面要讲到的mSystemThread也是static。

3)ActivityThread.systemMain()

    public static ActivityThread systemMain() {
        HardwareRenderer.disable(true);//初始化hardwareRenderer
        ActivityThread thread = new ActivityThread();//引入ResourceManager
        thread.attach(true);
        return thread;
    }

主要是ActivityThread.attach():

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                                                    UserHandle.myUserId());
            try {
                mInstrumentation = new Instrumentation();
                ContextImpl context = new ContextImpl();
                context.init(getSystemContext().mPackageInfo, null, this);
                Application app = Instrumentation.newApplication(Application.class, context);
                mAllApplications.add(app);
                mInitialApplication = app;
                app.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
            @Override
            public void onConfigurationChanged(Configuration newConfig) {
                synchronized (mResourcesManager) {
                    // We need to apply this change to the resources
                    // immediately, because upon returning the view
                    // hierarchy will be informed about it.
                    if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                        // This actually changed the resources!  Tell
                        // everyone about it.
                        if (mPendingConfiguration == null ||
                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                            mPendingConfiguration = newConfig;
                            
                            sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                        }
                    }
                }
            }
            @Override
            public void onLowMemory() {
            }
            @Override
            public void onTrimMemory(int level) {
            }
        });
    }

(1)android.ddm.DdmHandleAppName.setAppName(“system_process”, UserHandle.myUserId());

ddm是Dalvik Debug Monitor缩写,
具体干嘛的不清楚,谁指点一下哦?

(2)Instrumentation类

(3)context

context第一次真正出现应该就是这里了:

ContextImpl context = new ContextImpl();
context.init(getSystemContext().mPackageInfo, null, this);

虽然这里的context只是函数内局部变量,可是真正做的事情却很多。

先来看getSystemContext():

    public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                ContextImpl context =
                    ContextImpl.createSystemContext(this);
                LoadedApk info = new LoadedApk(this, "android", context, null,
                        CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
                context.init(info, null, this);
                context.getResources().updateConfiguration(mResourcesManager.getConfiguration(),
                        mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
                mSystemContext = context;
                //Slog.i(TAG, "Created system resources " + context.getResources()
                //        + ": " + context.getResources().getConfiguration());
            }
        }
        return mSystemContext;
    }

这里主要的目的是创建mSystemContext:

static ContextImpl mSystemContext = null;

这可是系统一直用到的,所以上面提到的context虽然是临时的,但是目的却很关键。

继续看,context是通过ContextImpl.createSystemContext(this);来创建的:

    static ContextImpl createSystemContext(ActivityThread mainThread) {
        final ContextImpl context = new ContextImpl();
        context.init(Resources.getSystem(), mainThread, Process.myUserHandle());
        return context;
    }

需要说明一下Resources.getSytem():

    public static Resources getSystem() {
        synchronized (sSync) {
            Resources ret = mSystem;
            if (ret == null) {
                ret = new Resources();
                mSystem = ret;
            }

            return ret;
        }
    }

还记得
android zygote之启动过程分析中提到的zygoteInit.main?其中有个preload();而随后
android 系统资源的加载和获取解析了过程,其中最关键的就是:

mResources = Resources.getSystem();

而这个mSystem是个static,所以这里ret在zygote的时候就注定了以后不会再为null了。包括Resources的构造函数中的mAssets也是static类型,这也是再zygote的时候定义好了的。

讲完了Resources.getSystem,再来看一下context.init函数:

    final void init(Resources resources, ActivityThread mainThread, UserHandle user) {
        mPackageInfo = null;
        mBasePackageName = null;
        mOpPackageName = null;
        mResources = resources;
        mMainThread = mainThread;
        mContentResolver = new ApplicationContentResolver(this, mainThread, user);
        mUser = user;
    }

作为systemcontext,这个时候mPackageInfo 等还是null,返回ActivityThread中继续看一下getSystemContext,讲完了createSystemContext,继续看一下一直会看到的packageInfo,这个对象的类型是LoadedApk:

LoadedApk info = new LoadedApk(this, "android", context, null,
    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);

LoadedApk是加载apk的相关类,详细的code不贴了,可以看到LoadedApk有两个构造函数,一个是针对普通apk的, 另一个是针对systemcontext的。这里的构造函数目的是创建了ApplicationInfo,还有就是mClassLoader、mResources等,不过注意mApplicationInfo.packageName、mPackageName都是等于“android”。注意这个LoadedApk构造函数,包括这个“android”等会有介绍到。

LoadedApk创建玩之后会再一次调用context.init:

    final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
        init(packageInfo, activityToken, mainThread, null, null, Process.myUserHandle());
    }

    final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread,
            Resources container, String basePackageName, UserHandle user) {
        mPackageInfo = packageInfo;
        if (basePackageName != null) {
            mBasePackageName = mOpPackageName = basePackageName;
        } else {
            mBasePackageName = packageInfo.mPackageName;
            ApplicationInfo ainfo = packageInfo.getApplicationInfo();
            if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
                // Special case: system components allow themselves to be loaded in to other
                // processes.  For purposes of app ops, we must then consider the context as
                // belonging to the package of this process, not the system itself, otherwise
                // the package+uid verifications in app ops will fail.
                mOpPackageName = ActivityThread.currentPackageName();
            } else {
                mOpPackageName = mBasePackageName;
            }
        }
        mResources = mPackageInfo.getResources(mainThread);
        mResourcesManager = ResourcesManager.getInstance();

        CompatibilityInfo compatInfo =
                container == null ? null : container.getCompatibilityInfo();
        if (mResources != null &&
                ((compatInfo != null && compatInfo.applicationScale !=
                        mResources.getCompatibilityInfo().applicationScale)
                || activityToken != null)) {
            if (DEBUG) {
                Log.d(TAG, "loaded context has different scaling. Using container's" +
                        " compatiblity info:" + container.getDisplayMetrics());
            }
            if (compatInfo == null) {
                compatInfo = packageInfo.getCompatibilityInfo();
            }
            mDisplayAdjustments.setCompatibilityInfo(compatInfo);
            mDisplayAdjustments.setActivityToken(activityToken);
            mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
                    Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
        } else {
            mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
            mDisplayAdjustments.setActivityToken(activityToken);
        }
        mMainThread = mainThread;
        mActivityToken = activityToken;
        mContentResolver = new ApplicationContentResolver(this, mainThread, user);
        mUser = user;
    }

这里应该是进一步的初始化mSystemContext了,之前的init说过,mPackageInfo等都是null,这里就详细的赋值了。mPackageInfo就是之前创建的LoadedApk,mBasePackageName、mOpPackageName都是之前创建LoadedApk传进来的“android”,mResources、mResourcesManager不用多说了,之前都介绍过了。

到这里这个ActivityThread 中这个static mSystemContext就完全创建ok了。

回到最开始,这里context是真正第一次出现,这里发现context.init跟getSystemContext中的context.init重复了,不知道google当初是怎么想的。

(4)创建application对象app

Application app = Instrumentation.newApplication(Application.class, context);
mAllApplications.add(app);
mInitialApplication = app;
app.onCreate();

这里具体的没有明白?

刚开始我也不太清楚,整个过程到底是干什么?显示实例化一个局部的context变量,而不是全局的,利用这个context只是做一个init,在init的时候会传入LoadedApk,这个应该是apk的所有相关信息的集合,为什么会在这里体现出来,而且LoadedApk构造的时候传入了一个package name是android,直到我看到一个东西,才完全明白这个ActivityThread 中attach函数的真正目的:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android" coreApp="true" android:sharedUserId="android.uid.system"
    android:sharedUserLabel="@string/android_system_label">

上面这段code是AndroidManifest.xml中部分,package name是 —> android,这下就解释通了。这里创建的Application 就是这个应用了,可以看出一个ActivityThread可以运行多个application,这里的application指的是android,而且,这个android 应用被设置为mInitialApplication。

在回头看一下LoadedApk的构造函数:

    public LoadedApk(ActivityThread activityThread, String name,
            Context systemContext, ApplicationInfo info, CompatibilityInfo compatInfo) {
        mActivityThread = activityThread;
        mApplicationInfo = info != null ? info : new ApplicationInfo();
        mApplicationInfo.packageName = name;
        mPackageName = name;
        mAppDir = null;
        mResDir = null;
        mSharedLibraries = null;
        mDataDir = null;
        mDataDirFile = null;
        mLibDir = null;
        mBaseClassLoader = null;
        mSecurityViolation = false;
        mIncludeCode = true;
        mClassLoader = systemContext.getClassLoader();
        mResources = systemContext.getResources();
        mDisplayAdjustments.setCompatibilityInfo(compatInfo);
    }

就是创建了android 这个application,实例化了一个ApplicationInfo,指定了mApplicationInfo.packageName,mPackageName都为android。最关键的是mClassLoader、mResources、mDisplayAdjustments。

说了半天这个android应用,也提出了他的AndroidManifest.xml,那么这个android应用到底是什么呢?bingo,就是framework-res.apk。

(5)DropBox.setReporter(new DropBoxReporter());

(6)ViewRootImpl.addConfigCallback(new ComponentCallbacks2(){});

向ViewRootImpl注册一个callback用于接收ConfigurationChanged事件(例如横竖屏切换、输入法弹出等),我们将在介绍WindowsManager的时候来分析如果dispatch这些事件到具体的activity当中。

4)通过ActivityThread分析后mSystemThread = at;这里的mSystemThread同mSelf,都是static

5)初始化AMS的mContext、mFactoryTest、mIntentFirewall、mStackSupervisor

        Context context = at.getSystemContext();
        context.setTheme(android.R.style.Theme_Holo);
        m.mContext = context;
        m.mFactoryTest = factoryTest;
        m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());

        m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper);

        m.mBatteryStatsService.publish(context);
        m.mUsageStatsService.publish(context);
        m.mAppOpsService.publish(context);

主要创建IntentFirewall,而IntentFirewall/data/system/ifw/ifw.xml or /data/secure/system/ifw/ifw.xml读取出来activitybroadcastservice,并时刻监听着文件是否改变 ,而IntentFirewallInterface则是看是否是ActivityManagerService的进程id而下面BatteryStatsServiceUsageStatsServiceAppOpsService.则是把服务注册掉binder manager

6)m.startRunning(null, null, null, null);

    public final void startRunning(String pkg, String cls, String action,
            String data) {
        synchronized(this) {
            if (mStartRunning) {
                return;
            }
            mStartRunning = true;
            mTopComponent = pkg != null && cls != null
                    ? new ComponentName(pkg, cls) : null;
            mTopAction = action != null ? action : Intent.ACTION_MAIN;
            mTopData = data;
            if (!mSystemReady) {
                return;
            }
        }

        systemReady(null);
    }

因为进入startRunning时mStartRunning和mSystemReady都为false,所以这里只是设置mStartRunning为true,mTopComponent为null,mTopAction为Intent.ACTION_MAIN,mTopData为null就直接返回。

到这里ActivityManagerService.main就全部解析完成。

总结一下:

main中的AThread中创建了一个looper,然后实例化了一个AMS,也就是mSelf;接着实例化了一个static 的ActivityThread,也就是mSystemThread,在ActivityThread中实例化了Application,即framework-res.apk;接着就是一些设置,如mContext、mFactoryTest、mIntentFirewall、mStackSupervisor、mBatteryStatsService、mUsageStatsService、mAppOpsService;startRunning。

    原文作者:私房菜
    原文地址: https://blog.csdn.net/shift_wwx/article/details/45742179
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞