ソース分析:Activityの起動プロセス(1)

14577 ワード

Activity#startActivityForResult


ActivityのstartActivityメソッドから解析を開始します.このメソッドにはいくつかのリロード方法がありますが、最終的にはstartActivity ForResultメソッドが呼び出されます.このメソッドは次のように実現されます.
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) { // 
            //...
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);    // Instrumentation execStartActivity (exec execute , )
            //...
        } else {
            //...
        }
    }

InstrumentationのexecStartActivityメソッドを見てみましょう

Instrumentation#execStartActivity(API25)

  • Instrumentationクラスは、各アプリケーションとシステムのインタラクションを管理する執事に相当します.Instrumentationは、任意のアプリケーションの実行前に初期化され、各プロセスには1つのInstrumentationオブジェクトしか存在せず、各Activityには、システムとアプリケーション間のすべてのインタラクションを監視するための実際の参照があります.
  • ここではActivityを本格的に起動する方法
  • を見ることができます.
        public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
    
            //...
    
            try {
                //...
    
                // Activity
                int result = ActivityManagerNative.getDefault() //ActivityManagerNative.getDefault() IActivityManager 
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
    
                // ,            
                checkStartActivityResult(result, intent);
            } catch (RemoteException e) {
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        }
    
  • のうち、IActivityManagerインタフェースの具体的な実装は、ActivityManagerService(以下、AMSと略す)である.AMSはActivityManagerNativeから継承され、ActivityManagerNativeはBinderから継承されIActivityManagerが実現されるため、AMBもBinderである.ただしAPI 26ではAMSはAMNを継承するのではなくIActivityManagerを継承する.Stub.(注意:API 26ではAMNは廃止され、その内部のエージェントクラスActivity Management Proxyは削除されている.これはAPI 26がActivityを起動した時点でAMSとの通信メカニズムがAIDL方式に変更されているため、詳細は同ブログを参照)
  • ActivityManagerNative.getDefault()

        static public IActivityManager getDefault() {
            return gDefault.get();
        }
    

    gDefaultの定義は次のとおりです.
        private static final Singleton gDefault = new Singleton() {
            protected IActivityManager create() {
                IBinder b = ServiceManager.getService("activity");
                IActivityManager am = asInterface(b);
                return am;
            }
        };
    

    Singletonは、getメソッドを最初に呼び出すとcreateメソッドでオブジェクトを作成し、後続の呼び出しでは前に作成したオブジェクトを直接返します.

    Instrumentation#execStartActivity(API26)


    API 26では、Activityを実際に起動するコードがいくつか変更されています.
        //ActivityManager.getService()  IActivityManager 
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
    

    ActivityManager.getService()


    ActivityManagerを見てgetService()は何を返しますか?
        public static IActivityManager getService() {
            return IActivityManagerSingleton.get();
        }
        private static final Singleton IActivityManagerSingleton =
                new Singleton() {
                    @Override
                    protected IActivityManager create() {
                        final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                        // ,Context.ACTIVITY_SERVICE = "activity";
                        final IActivityManager am = IActivityManager.Stub.asInterface(b);
                        return am;
                    }
                };
    

    高低バージョンは、サービス側(システムプロセス)のAMSのIBinderオブジェクトを先に取得し、得られたIBinderオブジェクトからIActivityManager(システムプロセスのAMSのappプロセスのbinderエージェント)を生成する

    ActivityManagerService#startActivity


    実装はバージョンによって異なりますが、最終的にはIActivityManagerインタフェースオブジェクトが返され、IActivityManagerインタフェースの実装クラスはAMSなので、最終的にはAMSのstartActivityメソッドが呼び出されます
        @Override
        public final int startActivity(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                    resultWho, requestCode, startFlags, profilerInfo, bOptions,
                    UserHandle.getCallingUserId());
        }
    
        @Override
        public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
            //...
            // TODO: Switch to user app stacks here.
            return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                    profilerInfo, null, null, bOptions, false, userId, null, null);
        }
    
  • ここでmActivity StarterはActivity Starterオブジェクトであり、Activity Starterクラスは主にActivityのIntentとFlagsの処理を担当し、関連するStackとTaskRecordもある.
  • API 23および以前のバージョンでは、returnは、Activity StackSupervisorのstartActivity MayWaitメソッドを呼び出す(このメソッドの実装はActivity Starterと同様、むしろActivity Starterがそのメソッドをそのまま運ぶ)
  • である.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    

    しかしAPI 24では、Activity StackSupervisorは、Activity StartyStarterにおいてstartActivity MayWaitメソッドを除去する.

    またいくつかのメソッドを呼び出し続けました


    ActivityStarter#startActivityMayWait

  • startActivity MayWait:IntentからActivityの起動情報(ResolveInfoとActivity Info)を取得し、呼び出し元のPidとUid(CallingPidとCallingUid)
  • を取得する
  • startActivity MayWait startActivity Lockedメソッド
  • の呼び出しを続行
        //...
        int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor,
                resultTo, resultWho, requestCode, callingPid,
                callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                inTask);
        //...
        return res;
    

    ActivityStarter#startActivityLocked

  • startActivity Locked:Activityのコア情報を含むActivityレコードを作成する
  • startActivity Locked startActivity Uncheckedメソッドの呼び出しを続行
  •     //...
        try {
            //...
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
        }
        //...
        return err;
    

    ActivityStarter#startActivityUnchecked

  • startActivity Unchecked:起動したFlag情報に基づいてTaskRecordを設定し、完了後にActivity StackSupervisorクラスのresumeFocusedStackTopActivity Lockedメソッドを実行し、起動を続行します.
  •     //...
    
        //  , dontStart true.
        final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
        if (dontStart) {
            //...
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();  //mSupervisor ActivityStackSupervisor 
            }
            //...
        }
    

    Activity StackSupervisorとActivity Stack間の相互ジャンプ


    ActivityStackSupervisor#resumeFocusedStackTopActivityLocked

        boolean resumeFocusedStackTopActivityLocked() {
            return resumeFocusedStackTopActivityLocked(null, null, null);
        }
        boolean resumeFocusedStackTopActivityLocked(
                ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
            if (targetStack != null && isFocusedStack(targetStack)) {
                return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
                //targetStack ActivityStack 
            }
            final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
            if (r == null || r.state != RESUMED) {
                mFocusedStack.resumeTopActivityUncheckedLocked(null, null); //mFocusedStack ActivityStack 
            }
            return false;
        }
    

    Activity StackのresumeTopActivity UncheckedLockedメソッドも呼び出されました

    ActivityStack#resumeTopActivityUncheckedLocked

        boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            if (mStackSupervisor.inResumeTopActivity) {
                // Don't even start recursing.
                return false;
            }
            boolean result = false;
            try {
                // Protect against recursion.
                mStackSupervisor.inResumeTopActivity = true;
                if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                    mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                    mService.updateSleepIfNeededLocked();
                }
                result = resumeTopActivityInnerLocked(prev, options); // resumeTopActivityInnerLocked 
            } finally {
                mStackSupervisor.inResumeTopActivity = false;
            }
            return result;
        }
    

    最後に返されるresultの値は、resumeTopActivity InnerLockedメソッドを呼び出すことによって得られます.

    ActivityStack#resumeTopActivityInnerLocked

        mStackSupervisor.startSpecificActivityLocked(next, true, false);   
        //mStackSupervisor ActivityStackSupervisor 
    

    Activity StackSupervisorのstartSpecificActivity Lockedメソッドも呼び出されました

    ActivityStackSupervisor#startSpecificActivityLocked

        void startSpecificActivityLocked(ActivityRecord r,
                boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
            ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                    r.info.applicationInfo.uid, true);
            r.task.stack.setLaunchTime(r);
            if (app != null && app.thread != null) {
                try {
                    //...
    
                    // activity 
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } catch (RemoteException e) {
                    //...
                }
            }
            //...
        }
    

    ついに、ここでrealStartActivity Lockedメソッドを呼び出してactivityを本格的に起動しました

    API 23と以前のバージョンのいくつかの違い

  • 『Android開発芸術探索』を見ていると、AMSのstartActivity AssUserがActivity StackSupervisorクラスを呼び出すstartActivity MayWaitメソッドであることがわかり、これも後のいくつかのメソッド呼び出しの違いを招いている.

  • ActivityStackSupervisor#startActivityMayWait


    ここでのロジックはAPI 24バージョンと同じですが、Activity StackSupervisorクラスのstartActivity Lockedメソッドが呼び出されます
        //...
    
        int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                voiceSession, voiceInteractor, resultTo, resultWho,
                requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                componentSpecified, null, container, inTask);
        //...
    
        return res;
    

    ActivityStackSupervisor#startActivityLocked

        //...
    
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);
    
        //...
    
        return err;
    

    ここではまたstartActivity UncheckedLockedメソッドを呼び出し続けます(API 24の名前とは違いますがパラメータは同じです)

    ActivityStackSupervisor#startActivityUncheckedLocked

        // 
    
        if (doResume) {
            targetStack.resumeTopActivityLocked(null, options);
        }
        if (doResume) {
            targetStack.resumeTopActivityLocked(null);  //targetStack ActivityStack 
        }
    

    Activity StackのresumeTopActivity Lockedメソッドの呼び出しを続行

    ActivityStack#resumeTopActivityLocked

        final boolean resumeTopActivityLocked(ActivityRecord prev) {
            return resumeTopActivityLocked(prev, null);
        }
        final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
            if (mStackSupervisor.inResumeTopActivity) {
                // Don't even start recursing.
                return false;
            }
            boolean result = false;
            try {
                // Protect against recursion.
                mStackSupervisor.inResumeTopActivity = true;
                if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                    mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                    mService.updateSleepIfNeededLocked();
                }
                result = resumeTopActivityInnerLocked(prev, options);
            } finally {
                mStackSupervisor.inResumeTopActivity = false;
            }
            return result;
        }
    

    この方法はAPI 24以降のresumeTopActivity UncheckedLocked方法の実装と同じであり,名前が異なるだけで,その後の呼び出しはAPI 24以降と同じであることがわかる.

    小結

  • 総じて言えば、API 24からAMS(Activity Management Service)とASS(Activity StackSupervisor)の間にActivity Staterが追加され、Activityの起動を管理している.

  • ActivityStackSupervisor#realStartActivityLocked

  • realStartActivity Lockedメソッドはまた何をしたのか、最後にどのメソッドが最終的にActivityを起動したのか.紙面の問題のため、私は後の分析を別の文章に置いた:ソース分析:Activityの起動過程(2)
  • リファレンス

  • 『Android開発芸術探索』
  • Android 7.0 startActivity()ソースコード解析およびいくつかの問題に対する思考
  • ソースコード分析:startActivityプロセス
  • 探索7.x,包括解析Activity起動フレームワーク(1)