Android 소스 코드(5) --- 애플리케이션 시작 프로세스

8857 단어

앱 실행 프로세스



각 Application Linux 프로세스에서 Android 운영 체제는 프로세스를 시작하며 Android 구성 요소를 실행해야 하거나 오랫동안 사용하지 않거나 시스템이 다른 앱의 메모리를 회수해야 하는 경우 프로세스가 종료됩니다.


  • 리뷰: 지난 블로그에서 Launcher 시작 과정을 소개하고 마지막으로 바탕 화면 아이콘을 클릭하여 응용 프로그램을 시작했습니다

  • protected void onListItemClick(ListView l, View v, int position, long id) {
            Intent intent = intentForPosition(position);
            startActivity(intent);
        }
    
    public void startActivity(Intent intent, @Nullable Bundle options) {
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
        
        // 这里 options 为null,继续走satrtActivityForResult();
        
        public void startActivityForResult(Intent intent, int requestCode) {
            startActivityForResult(intent, requestCode, null);
        }
        
        public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
            if (mParent == null) {
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
                if (requestCode >= 0) {
                    mStartedActivity = true;
                }
    
                cancelInputsAndStartExitTransition(options);
                // TODO Consider clearing/flushing other event sources and events for child windows.
            } else {
                if (options != null) {
                    mParent.startActivityFromChild(this, intent, requestCode, options);
                } else {
                    // Note we want to go through this method for compatibility with
                    // existing applications that may have overridden it.
                    mParent.startActivityFromChild(this, intent, requestCode);
                }
            }
        }
    



  • mInstrumentation.execStartActivity()가 execStartActivity를 먼저 실행합니다.

  • public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
            Uri referrer = target != null ? target.onProvideReferrer() : null;
            if (referrer != null) {
                intent.putExtra(Intent.EXTRA_REFERRER, referrer);
            }
            if (mActivityMonitors != null) {
                synchronized (mSync) {
                    final int N = mActivityMonitors.size();
                    for (int i=0; i= 0 ? am.getResult() : null;
                            }
                            break;
                        }
                    }
                }
            }
            try {
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess();
                int result = ActivityManagerNative.getDefault()
                    .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;
        }
    



  • 여기에서 ActivityManagerNative.getDefault().startActivity는 Activity로 점프하기 위해 ActivityManagerNative를 가져옵니다.ActivityManagerNative는 실제로 프로세스 간 통신인 Binder에서 통합되고 ActivityManagerService는 여기에서 ActivityManagerNative에서 상속됩니다.프로세스 간 통신 시 ActivityManagerNative.startActivity()를 호출하십시오. ActivityManagerService.startActivity()를 호출하면 Native는 클라이언트에 해당하고 Service는 서버에 해당합니다.
  • 따라서 ActivityManagerService의 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 options) {
            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, options,
                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 options, int userId) {
            enforceNotIsolatedCaller("startActivity");
            userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                    false, ALLOW_FULL_ONLY, "startActivity", null);
            // TODO: Switch to user app stacks here.
            return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                    profilerInfo, null, null, options, false, userId, null, null);
        }
        
         final int startActivityMayWait(IApplicationThread caller, int callingUid,
                String callingPackage, Intent intent, String resolvedType,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int startFlags,
                ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
                Bundle options, boolean ignoreTargetSecurity, int userId,
                IActivityContainer iContainer, TaskRecord inTask) {
           
            intent = new Intent(intent);
    
            // Collect information about the target of the Intent.
            ActivityInfo aInfo =
                    resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
    
            ActivityContainer container = (ActivityContainer)iContainer;
            synchronized (mService) {
                if (container != null && container.mParentActivity != null &&
                        container.mParentActivity.state != RESUMED) {
                    // Cannot start a child activity if the parent is not resumed.
                    return ActivityManager.START_CANCELED;
                }
                .......
                
                int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                        voiceSession, voiceInteractor, resultTo, resultWho,
                        requestCode, callingPid, callingUid, callingPackage,
                        realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                        componentSpecified, null, container, inTask);
    
                Binder.restoreCallingIdentity(origId);
    
                .......
    
                return res;
            }
        }
    

  • 호출 관계 보기, startActivity() --> startActivityAsUser() --> startActivityMayWait() --> startActivityLocked()
  • 계속 추적, startActivityLocked() -->startActivityUncheckedLocked() --> ActivityStack.startActivityLocked() --> ActivityStackSupervisor.resumeTopActivitiesLocked() --> ActivityStack.resumeTopActivityLocked() --> ActivityStack.resumeTopActivityInnerLocked > ActivityStackSupervisor.startSpecificActivityLocked() --> AMS.startProcessLocked()

  • startProcessLocked() 보기:
    ......
    
     checkTime(startTime, "startProcess: asking zygote to start proc");
                Process.ProcessStartResult startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                        app.info.dataDir, entryPointArgs);
                checkTime(startTime, "startProcess: returned from zygote!");
                
    ......
    

  • Process.start() 프로세스를 시작했습니다. app.processName은 프로세스 이름입니다
  • .

    요약하다



  • 응용 프로그램의 4가지 구성 요소가 시작되면 현재 프로세스가 시작되지 않고 현재 프로세스가 먼저 시작됩니다.
  • 각 애플리케이션은 자체 Linux 프로세스와 JVM 운영 환경을 가지며 프로세스는 바인더를 통해 통신합니다.
  • 순서도
  • 좋은 웹페이지 즐겨찾기