ActivityManagerService(一)


文章の出所:http://blog.csdn.net/shift_wwwx
前書き:前のAndroid SystemServerを詳しく分析してみました.systeemServerの起動過程は複雑な分析が多いですが、systemserverはandroid起動の第一歩です.多くのserviceはこのプロセスで起動しています.これらこそがandroidを構成する鍵です.AMSはandroidアプリケーションの一番重要なserviceと言えます.伝説のアンディの4つのコンポーネントはそれで制御します.ソースコードによって分析しますが、足りないところが多いと思います.
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;
    }
は、コード内のコメントに注意する.
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を作成しました.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を見てください.
いくつかの変数の注意が必要です.mBroadcastQues、mbgBroadcastQue、mBgBroadcastQue、mServices、mProvider Mapの4つのコンポーネントがここに現れました.もう一つの後期に紹介します.他の変数もあります.mBatteryStats Service、mProcess Stats、mUsageStats Service、mApp OpsService、mGrantFile、mStartdeUsers、mComppartModePackage、mProcess CputThreadなど.
コードから見れば、/data/system/の下で、いくつかのファイルを作成してandroidシステムの状態を管理しています.例えば、batterystats.binは電池状態です.そして、procstats管理プロセスのapps.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.atch()です.
    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.DdmHandleApple.setApName(「system upcess」、UserHandle.mUserId();
ddmはDalvik Debug Monitorの略語で、
具体的に何がよく分かりませんか?誰が教えてくれますか?
(2)Instruumentation類
(3)context
contextが初めて本当に現れたのはここです.
ContextImpl context = new ContextImpl();
context.init(getSystemContext().mPackageInfo, null, this);
ここのcontextは関数内の局部変数ですが、本当にやることが多いです.
まずget System Contect():
    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;
    }
ここの主な目的はmSystemContectを作成することです.
static ContextImpl mSystemContext = null;
これはシステムがずっと使っていますので、上記のcontextは臨時ですが、目的は肝心です.
引き続き見て、contextはContectImpl.creat SystemConteextを通じて(this)です.を選択して作成しました
    static ContextImpl createSystemContext(ActivityThread mainThread) {
        final ContextImpl context = new ContextImpl();
        context.init(Resources.getSystem(), mainThread, Process.myUserHandle());
        return context;
    }
は、Resources.get Sytem():
    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になりません.Resourceを含むコンストラクションの中のmAsssetsもstaticタイプです.これもzygoteの時に定義されました.
Resources.get Systemを説明しました.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;
    }
はsystem contextとして、この時mPackage Infoなどはnullです.ActivityThreadに戻って、gets SystemCotextを見続けて、createSystem Contextを説明しました.ずっと見ているpackage Infoを見てください.この対象のタイプはLoadedAkです.
LoadedApk info = new LoadedApk(this, "android", context, null,
    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
LoadedAkはappkをロードする関連カテゴリで、詳細なcodeは貼っていません.Loadedアプリには2つの構成関数があり、一つは普通のappkに対して、もう一つはsystemboxtに対するものです.ここのコンストラクタはApplication Infoを作成することを目的としています.またmClass Loader、mResourceなどですが、mApplication Info.package Name、mPackage Nameはすべて「android」に等しいです.このLoadedAnk構造関数に注意してください.この「android」などが紹介されます.
LoadedAnkはゲームを作成した後、もう一回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;
    }
ここではさらなる初期化mSystemContectであるべきです.以前のinitによると、mPackage Infoなどは全部nullです.ここで詳細な割り当てを行います.mPackage Infoは前に作成したLoadedArkです.mBasePackage Name、mOpPackage Nameは全部前にLoadedAkを作成して伝えられた「android」です.mResource、mResource Managerはもちろん、以前に紹介しました.
ここまでのActivityThreadのこのstatic mSystemContextは完全に作成okです.
最初に戻って、ここでcontextは本当に初めてです.ここでcontext.initとgets SystemConteextの中のcontext.initが重複しています.googleは当初どう思っていましたか?
(4)アプリオブジェクトの作成
Application app = Instrumentation.newApplication(Application.class, context);
mAllApplications.add(app);
mInitialApplication = app;
app.onCreate();
ここは具体的に分かりませんでしたか?
最初はよく分かりませんでしたが、全体の過程はいったい何をしていますか?全体的なものではなく、一部のcontext変数を表示します.このcontextを利用してinitを作って、initの時にLoadedAkに入ってきます.これはappkのすべての関連情報の集合です.なぜここに現れますか?このActivityThreadにおけるatch関数の本当の目的が完全に分かりました.
<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">
上記のコードはAndroid Manifest.xmlの中の部分で、package nameは-->androidです.これで説明が通ります.ここで作成したアプリはこのアプリケーションです.一つのActivityThreadは複数のアプリを実行できます.ここのアプリはandroidです.そして、このandroidアプリはmInitialアプリアプリに設定されています.
LoadedAnkの構造関数を振り返ってみます.
    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というアプリを作成して、Aplication Infoを実際に例化して、mApple Info.package Nameを指定しました.mPackage Nameはすべてandroidです.一番重要なのはmClass Loader、mResource、mDisplayAdjustomentsです.
このandroidアプリも彼のAndroid Manifest.xmlを提出しました.このAndroidアプリは一体何ですか?bingoとは、frame ework.ress.appkのことです.
(5)DropBox.set Report(new Drop BoxReport();
(6)View RootImpl.addConfigCallback(new ComponentCallbacks 2(){}
View RootImplにConfigrationChangedイベントを受信するために登録します.Windows Managerを紹介する時に、dispatchのような事件が具体的なactivityの中にあれば分析します.
4)ActivityThreadで分析した後、mSystemThread=at;ここのmSystemThreadとmSelfは全部staticです.
5)AMSを初期化するmContect、mFactoryTest、mIntent Firewall、mStock Supervisor
        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);
Intent Firewallを主に作成し、Intent Firewallから/data/system/ifw/ifw.xml or /data/secure/system/ifw/xmlからactivity,broadcast,serviceを読み取り、ファイルの変更を常時傍受しています. ,Intent FirewallInterfaceはActivityManagerServiceのプロセスidかどうかです.次のBatteryStits Serviceは、UsageStatits Service、AppOpsServiceです.サービスを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なので、ここではmStarrtRunningをtrueとし、mTopComponentをnullとし、mTopActをIntent.ACTIONとします.MAIN、mTopDataはnullで直接戻ります.
ここまでActivityManager Service.mainは全部解析しました.
まとめてみます
mainのAThreadでlooperを作成し、AMS、つまりmSelfを実例化しました.次に、ActivityThreadというstaticのActivityThreadを実例化しました.つまり、mSystemThreadは、ActivityThreadの中でAppplicationを実行しました.frame ew-rek.appkです.続いていくつかの設定があります.mConteext、mFactoryTest、mIntent Firewall、mStockSupervisor、mBatteryStats Service、mUsageStats Service、mAppOppServiceなどです.スターリング.