Android Activity 의 시작 프로 세 스 를 자세히 알 아 보기
activity 가 시작 하 는 절 차 는 두 부분 으로 나 뉜 다.하 나 는 activity 에서 startActivity(Intent intent)방법 으로 Activity 를 시작 하 는 것 이다.둘째,데스크 톱 에서 아이콘 을 누 르 면 App 을 시작 하고 Activity 를 표시 합 니 다.두 번 째 방식 은 첫 번 째 방식 에 비해 더욱 전면적 이기 때문에 본 고 는 두 번 째 절차 로 분석 할 것 이다.
간명 하 다
우리 핸드폰 의 데스크 톱 은 Launcher 라 는 Activity 로 핸드폰 에 있 는 응용 아이콘 을 나열 하고 아이콘 에는 apk 를 설치 할 때 분석 하 는 응용 기본 시작 페이지 등 정보 가 포함 되 어 있 습 니 다.아이콘 을 눌 렀 을 때 시작 할 App 과 Launcher,AMS,Zygote 소속 프로 세 스 가 다 르 기 때문에 Launcher 와 AMS,AMS 와 Zygote,AMS 와 새 App 등 네 가지 가 여러 번 통신 해 야 하나의 App 을 시작 할 수 있 습 니 다.그리고 Activity 를 시작 합 니 다.전체적인 순서 도 는 다음 과 같 습 니 다.
다음은 소스 코드 에 따라 절 차 를 정리 하 겠 습 니 다.
1.Launcher 가 AMS 에 시작 Activity 보 내기
Launcher 자 체 는 Activity 입 니 다.사용자 가 아이콘 을 클릭 할 때 startActivity Safely 방법 을 호출 하고 마지막 으로 Activity.startActivity()로 호출 합 니 다.함 수 는 다음 과 같 습 니 다.
Launcher.java
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...
//
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
startActivity(intent, optsBundle);
...
}
Activity.java
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
...
if (options != null) {
//-1 requestCode
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken,this,intent, requestCode, options);
...
}
모든 Activity 는 Instrumentation 대상 을 가지 고 있 습 니 다.exec Start Activity 함 수 를 통 해 Activity 를 시작 하 는 절 차 를 계속 수행 합 니 다.이 함수 에는 mMainThread.getApplicationThread()가 들 어 왔 습 니 다.Activity Thread 의 내부 클래스 ApplicationThread 를 얻 었 습 니 다.이것 은 Binder 대상 이 고 그 후에 AMS 는 이 대상 을 통 해 App 과 통신 합 니 다.
Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
int result = ActivityTaskManager.getService().startActivity(whoThread,who.getBasePackageName(),
who.getAttributionTag(),intent,intent.resolveTypeIfNeeded(who.getContentResolver()),
token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
...
}
ActivityTaskManager.java
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
}
};
이 단 계 는 Launcher 가 AMS 에 통신 하기 시 작 했 습 니 다.서로 다른 프로 세 스 때문에 Binder 를 통 해 통신 해 야 합 니 다.IActivity Task Manager 는 AMS 엔 드 Binder 를 대리 하 는 대상 이 고 그 후에 AMS 는 startActivity 를 시작 합 니 다.여기 서 Launcher 가 AMS 에 Activity 를 시작 하 라 고 요청 하면 프로 세 스 가 끝 납 니 다.2.AMS 가 Activity 를 시작 하고 Launcher 에 Paused 상태 로 들 어 오 라 고 알 립 니 다.
현재 프로 세 스 는 AMS,즉 다른 프로 세 스 입 니 다.이전 단 계 는 대 리 를 통 해 AMS 의 startActivity 방법 으로 호출 되 었 습 니 다.다음 호출 은 다음 과 같 습 니 다.
ActivityTaskManagerService.java
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
...
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();
}
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
위의 몇 단 계 는 주로 권한 검 사 를 하 는 것 이다.
ActivityStarter.java
int execute() {
...
res = executeRequest(mRequest);
...
}
//
ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false , next);
}
...
mStackSupervisor.startSpecificActivity(next, true, false);
...
}
startPausing Locked 방법 은 주로 Launcher 에 Paused 상태 로 들 어가 라 고 알 리 는 것 입 니 다.이 상태 에 들 어간 후에 Activity Stack Supervisor.startSpecific Activity 방법 으로 새로운 App 프로 세 스 상 태 를 판단 하여 서로 다른 응답 을 합 니 다.다음 과 같 습 니 다.
ActivityStackSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Activity
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
// Activity( Activity )
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
// AMS Zygote
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
지금까지 Launcher 와 AMS 의 통신,그리고 AMS 와 Zygote 프로 세 스 의 통신 이 완료 되 었 습 니 다.다음은 시작 할 App 의 스 레 드,즉 Activity Thread 를 만 들 것 입 니 다.3.새로운 프로 세 스 시작,Activity Thread 의 main 함수 입구
이전 Zygote 에서 새 프로 세 스 를 시작 할 때 Activity Thread.main 함 수 를 표시 합 니 다.Zygote 에서 새 프로 세 스 를 만 든 후 이 방법 을 반사 적 으로 호출 합 니 다.현재 새 App 프로 세 스 에 있 습 니 다.
ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
...
Looper.loop();
...
}
private void attach(boolean system, long startSeq) {
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
}
ActivityManagerService.java
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
...
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
...
}
여 기 는 주로 Looper 와 Activity Thread 대상 을 만 든 다음 에 현재 응용 프로그램 Thread 를 AMS 에 등록 합 니 다.응용 프로그램 Thread 는 Activity Thread 의 내부 클래스 로 IApplicationThread.Stub 를 실 현 했 습 니 다.이 대상 으로 프로 세 스 를 뛰 어 넘 을 수 있 습 니 다.위의 코드 논 리 는 두 단계 로 나 뉘 는데 첫 번 째 단 계 는 AMS 가 응용 프로그램 Thread 를 연결 할 때 H.BIND 를 보 냈 습 니 다.APPLICATION 의 Message 는 Handler 에서 이 메 시 지 를 처리 할 때 Application 의 onCreate 방법 을 호출 했 습 니 다.두 번 째 단 계 는 mAtm Internal 의 attachApplication 에서 Activity Stack Supervisor.realStart Activity Locked 방법 으로 층 층 이 호출 되 었 습 니 다.전체적으로 다음 과 같 습 니 다.
public final void bindApplication(String processName, ApplicationInfo appInfo,
ProviderInfoList providerList, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
...
sendMessage(H.BIND_APPLICATION, data);
}
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
private void handleBindApplication(AppBindData data) {
...
mInstrumentation.callApplicationOnCreate(app);
...
}
지금까지 새로운 앱 스 레 드 가 시작 되 고 애플 리 케 이 션 에 연결 되 어 있 습 니 다.4.액 티 비 티 만 들 기
ActivityStackSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
...
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// clientTransaction
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
...
}
Client Transaction 은 Activity 의 시작 정 보 를 관리 합 니 다.Client LifecycleManager 에서 실 행 됩 니 다.scheduleTransaction 방법 에서 EXECUTE 를 보 냈 습 니 다.TRANSACTION 의 메 시 지 는 Activity Thread 의 H 클래스 에 처리 한 다음 TransactionExecutor.execute()를 실행 한 다음 handle LaunchActivity 방법 을 실행 합 니 다.다음 과 같 습 니 다.
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
...
}
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
class H extends Handler {
...
public void handleMessage(Message msg) {
...
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
...
}
...
}
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
...
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}
다음은 Activity Thread 에서 후속 작업 을 처리 합 니 다.
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
...
return a;
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ContextImpl appContext = createBaseContextForActivity(r);
...
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
...
activity.setTheme(theme);
...
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
}
perform LaunchActivity 방법 에서 주로 다음 과 같은 몇 가지 일 을 했 습 니 다.루트 Activity 는 전체적으로 학습 의미 가 크 므 로 전체적인 절차 에 착안 하여 절차 가 통 하지 않 을 때 debug 를 할 수 있 습 니 다.Activity 의 전체 시작 프로 세 스:
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.