안드로이드 10 startActivity를 소스 코드 분석

소스를 기반으로 안드로이드 (10)

안드로이드 10.0 startActivity를 순서도

이 그림은 수명주기의 일부를 정제에 초점을 맞추고, 안드로이드 (10)가 활동을 관리 할 수 ​​있도록 설계된 ActivityTaskManager, 추가, ActivityManager의 작품의 일부를 인수

계측 이해

활동 첫번째 계측 호출을 통해 갈 것이다, 계측가 callActivityOnCreate, callActivityOnPause, callApplicationOnCreate 강력한 추적 활동 및 응용 프로그램 수명주기와 다른 통화를 포함, 그것은 또한 사용 프레임 워크를 테스트 응용 프로그램에 대한 기초로 사용된다. 이 방법은 개체 ActivityThread A는, 오브젝트가 ActivityThread 계측 개체를 보유하고, 각각의 활동 계측 소지에 보유

IPC는 어디 일이?

계측에서 system_server 프로세스 앱 IActivityTaskManager.aidl 과정에서 인터페이스를 통해 입력합니다 돌아 가기 앱 과정을 system_server에 의해 ClientTransaction에서 IApplicationThread.aidl 인터페이스

활동 스택을 관리하는 방법은?

ActivityRecord : 활동 ActivityRecord 형태는 활동 인스턴스에 ActivityRecord의 대응 기록 할
TaskRecord :이 실제 활동 스택 내부 ArrayList를 가지고있다 <ActivityRecord이>, 현재 스택의 모든 활동 기록
ActivityStack가 : 활동 스택 관리를 담당 멀티 매장 TaskRecord

부팅 모드 구성 매니페스트를 읽을 수있는 노드의 활동

도 매니페스트의 구성을 읽기

이 AndroidManifest.xml에, APK 스캔 로컬 디렉토리를 구문 분석을 주로 담당 IPC, PackageManagerService되지 않도록 ActivityInfo, 서비스 정보 부 (ServiceInfo), ProviderInfo 및 기타 정보를 포함 PackageManagerService # resolveIntentInternal 방법 ResolveInfo, ResolveInfo에 의해 반환 된 그림은,이 호출은 프로세스 system_server 이미 설치 관리 앱을 삭제 대기

어디에서 활동 매니페스트에 등록되어 감지가?

키 코드 ActivityStarter #의 startActivity를 방법 :

       if (err == ActivityManager.START_SUCCESS && aInfo == null) {
           // We couldn't find the specific class specified in the Intent.
           // Also the end of the line.
           err = ActivityManager.START_CLASS_NOT_FOUND;
       }

aInfo는 ActivityInfo이며, ActivityInfo 빈 원인 다음 오류가 반환됩니다. aInfo 그런에서 온입니까? 물론, 그것은 PackageManagerService # resolveIntentInternal 방법에 의해 구문 분석됩니다. 그런 다음 ActivityManager.START_CLASS_NOT_FOUND는, 이상 "당신이 당신의 AndroidManifest.xml에서이 활동을 선언 한;? 명시 적 활동 클래스 {XXX}을 (를) 찾을 수 없습니다"던져 후 리턴 값으로 계측 # checkStartActivityResult 방법을 발견

왜 효과 개별적으로 구성 taskAffinity을하지

키 코드 ActivityStarter 번호는 방법을 startActivityUnchecked :

  if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
         newTask = true;
         result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
  } else if (mSourceRecord != null) {
         result = setTaskFromSourceRecord();
  } else if (mInTask != null) {
         result = setTaskFromInTask();
  } else {
         result = setTaskToCurrentTopOrCreateNewTask();
  }

만 mLaunchFlags는 FLAG_ACTIVITY_NEW_TASK가 TaskRecord하는 새로운 활동 스택을 만들 갈 것이다 표시, 시스템은 taskAffinity의 상황 형 구성과 거래를하지 않았다. AndroidManifest.xml의 구성 즉 launchMode 어디 프로세스 및 mLaunchFlags 그것에 응답하여인가?
다음과 같이 ActivityStarter # computeLaunchingTaskFlags 방법 구성 mLaunchFlags 코드라는 ActivityStarter # startActivityUnchecked 방법은 다음과 같습니다

   if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
         Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
         mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
    }else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
         mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
    } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
         mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
    }

새 스택에 LAUNCH_SINGLE_INSTANCE 모드 시작을 볼 수 있고 그래서 우리는 이미 잘 알려진 규칙입니다

이해 ClientTransactionItem 및 ActivityLifecycleItem

그 트랜잭션을 실행하는 ClientTransaction, startActivity를, ONSTART는, onResume 이벤트가 트랜잭션에 저장되어 실행에서 onCreate 새로운 활동으로 ClientLifecycleManager 하나 또는 그 이상의 라이프 사이클 이벤트가 함께 그룹화 할 수 있습니다

만약 startActivity의 새로운 활동에서 onCreate 이벤트는 <ClientTransactionItem가>, 캐리어 LaunchActivityItem 유형 목록의 멤버 변수 ClientTransaction에 저장합니다. 즉 활동 이벤트를 시작, 또한 ClientTransactionItem 하위 범주를 LaunchActivityItem. 또 다른 NewIntentItem (onNewIntent 트리거 콜백), ActivityResultItem (트리거하여 onActivityResult), ConfigurationChangeItem (의 onConfigurationChanged 트리거 콜백) 및 기타 이벤트

onResume 이벤트 startActivity를 새로운 활동 ActivityLifecycleItem 유형의 변수 멤버 변수의 ClientTransaction에 저장하는 경우,이 변수는 캐리어의 수명주기의 최종 상태가 ResumeActivityItem입니다 나타냅니다. 서브 클래스의 ActivityLifecycleItem도 ClientTransactionItem

왜의 방법 활동 onPause 많은 시간이 소요되는 작업을하지?

ClientTransaction는 실행을 위해 메인 쓰레드 ActivityThread.H 메시지 큐에 추가 된 후 Parcelable scheduleTransaction 앱 IApplicationThread.aidl 방법에 의해 단말기로 전송되는 데이터, 및이다. 차례로 이전 의지는 우리가 할 수없는 일시 정지의 새로운 활동 활동을 전송하고 거래를 재개 한 다음 모두 거래 ActivityThread.H startActivity를 시간에 의해 순서로 일어날 시간이 소요만을 구현 방법 후하기 때문에, 방법 활동 onPause 작업을 onPause 라이프 사이클 이벤트 다음 활동을 실행하기 위해, 그렇지 않으면 새로운 인터페이스 디스플레이를 차단

활동 인스턴스 어디 작성?

ActivityThread에서 # performLaunchActivity 방법은 계측 # newActivity의 방법으로 개체 활동의 인스턴스를 생성합니다, 이후 콜백 활동의 계측 # callActivityOnCreate 방법에서 onCreate 방법이라고

앱 실행기를 시작 아이콘을 클릭

실행기는 같은 방법 startActivity를 호출하는 것입니다 시작 아이콘을 클릭,하지만 당신은 프로세스, ActivityStackSupervisor # startSpecificActivityLocked 방법의 핵심 코드를 작성해야합니다 :

   final WindowProcessController wpc =
           mService.getProcessController(r.processName, r.info.applicationInfo.uid);
   if (wpc != null && wpc.hasThread()) {
        //判断进程存在,继续启动
        realStartActivityLocked(r, wpc, andResume, checkConfig);
        return;
   }
   //进程不存在,创建进程
   final Message msg = PooledLambda.obtainMessage(
           ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
           r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
   mService.mH.sendMessage(msg);

startProcess 흐름도

접합자 프로세스 통신과 소켓 방식으로, 왜 더 안전하게, 단순히 그것의 바인더 일단 데이터를 복사 사용하지 채택? 바인더는 멀티 스레드 실행을 기반으로 멀티 스레드 포크가 교착 상태 발생, 또는 때문에 복사 -에 - 쓰기 메커니즘 허용되지 않으며, 동안 수정 된 접합자 안드로이드 과정, 포크 방법에 의해 생성 된 프로세스로

PROCESSLIST # startProcessLocked 방법, 엔트리 포인트 매개 변수의 값이 "android.app.ActivityThread을"통과에서 후속 수정란의 과정을 통해 전달합니다, 수정란 포크 새로운 프로세스 즉, ActivityThread 번호 주요 기능은 새로운 프로세스를 호출 할 것이다, 성공하기 앱 실제 부팅 항목

ActivityThread.main 흐름도

ActivityManagerService에서 #은 응용 프로그램의 예에 최초로 응용 프로그램 및 IApplicationThread에서 onCreate의 방법으로 콜백 프로세스를 생성하는 두 가지 핵심 논리의 실행 방법을 attachApplicationLocked 두 번째 집 활동을 시작하는 더, ActivityTaskManagerService # attachApplication 메소드를 호출하는 것입니다.
시작 활동과 일반 startActivity를 동일은 ActivityStackSupervisor # realStartActivityLocked 방법으로 호출됩니다

이해 ActivityThread 및 ApplicationThread

ActivityThread.main () 메소드는 진입 절차를 시작하는 메인 쓰레드는 루퍼 ActivityThread.H에서 메시지 처리를 초기화한다. ApplicationThread 구현하는 인터페이스 콜백 IApplicationThread.aidl AMS 시스템 및 서비스, 대부분은 네 개의 구성 요소의 작업이 관련되어 나타날 것을 ActivityThread 내부 클래스이며, 이는 메인 쓰레드에 바인더로 전환된다 처리기 ActivityThread.H에 메시지를 보낸다 스레드 처리

어떻게 매니페스트에 등록되지 않은 활동을 시작하는 방법?

매니페스트 system_server 정보 등록 처리의 실험을로드는 탐지 로직을 방해 할 수 없다. 그것은 매니페스트에서 일반적인 관행 작성 후 자리를 수정 등록되지 않은 활동 활동에 들어가기 전에, system_server 과정을 자리 표시 자 활동을 등록하고 다음 등록되지 않은 다시 앱 활동에 변화 system_server에서 반환하는 과정 기다린이다, 시작 그 필요성이 걸리지 :

ActivityTaskManager 후크 :

final Field singletonField = ActivityTaskManager.class
             .getDeclaredField("IActivityTaskManagerSingleton");
singletonField.setAccessible(true);
Singleton singleton = (Singleton) singletonField.get(null);
final Object activityTaskManagerObject = singleton.get();
final Field mInstanceField = Singleton.class.getDeclaredField("mInstance");
mInstanceField.setAccessible(true);
Object value = Proxy.newProxyInstance(ActivityTaskManager.class.getClassLoader()
     , new Class[]{Class.forName("android.app.IActivityTaskManager")}
     , new InvocationHandler() {
           @Override
           public Object invoke(Object proxy,
                         Method method, Object[] args) throws Throwable {
              if ("startActivity".equals(method.getName())) {
                  Intent raw;
                  int index = 0;
                  for (int i = 0; i < args.length; i++) {
                     if (args[i] instanceof Intent) {
                        index = I;
                        break;
                     }
                  }
                  if (!(args[index] instanceof Intent)) throw new AssertionError();
                  raw = (Intent) args[index];
                  if (raw.getComponent().getClassName()
                         .equals("com.yinghao.test.UnRegisterActivity")) {
                      ntent newIntent = new Intent();
                      //将未注册的 UnRegisterActivity 替换为占位 FakeActivity
                      newIntent.setComponent(new ComponentName("com.yinghao.test", 
                                   FakeActivity.class.getName()));
                      //记录 UnRegisterActivity
                      newIntent.putExtra(EXTRA_TARGET_INTENT, raw); 
                      args[index] = newIntent;
                  }
              }
              return method.invoke(activityTaskManagerObject, args);
           }
});
mInstanceField.set(singleton, value);

ActivityThread 후크 :

ActivityThread activityThread = ActivityThread.currentActivityThread();
Field mH1 = activityThread.getClass().getDeclaredField("mH");
mH1.setAccessible(true);
final Handler mH = (Handler) mH1.get(activityThread);
Field mCallBackField = Handler.class.getDeclaredField("mCallback");
mCallBackField.setAccessible(true);
mCallBackField.set(mH, new Handler.Callback() {
 @Override
 public boolean handleMessage(Message msg) {
  try {
   if (msg.what == 159) { // ActivityThread.H.EXECUTE_TRANSACTION
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    Field mActivityCallbacksField = transaction
               .getClass().getDeclaredField("mActivityCallbacks");
    mActivityCallbacksField.setAccessible(true);
    List<ClientTransactionItem> clientTransactionItems = 
        (List<ClientTransactionItem>) mActivityCallbacksField.get(transaction);
    if (clientTransactionItems != null) {
     for (ClientTransactionItem c : clientTransactionItems) {
      if (c instanceof LaunchActivityItem) {
       //修正 Activity 启动事件实体 LaunchActivityItem
       LaunchActivityItem item = (LaunchActivityItem) c;
       Field intentField = item.getClass().getDeclaredField("mIntent");
       intentField.setAccessible(true);
       Intent intent = (Intent) intentField.get(item);
       Field mInfoField = item.getClass().getDeclaredField("mInfo");
       mInfoField.setAccessible(true);
       ActivityInfo aInfo = (ActivityInfo) mInfoField.get(item);
       Intent realIntent = intent.getParcelableExtra(EXTRA_TARGET_INTENT);
       if (realIntent != null) {
         //将占位 FakeActivity 改回未注册的 UnRegisterActivity
         intent.setComponent(realIntent.getComponent());
         aInfo.packageName = realIntent.getComponent().getPackageName();
         aInfo.name = realIntent.getComponent().getClassName();
       }
       }
     }
    }
   }
  } catch (Exception e) {

  }
  return false; //返回 false 正好可以让 ActivityThread 继续处理
 }
});

등록되지 않은 활동 startActivity를이어야 전제를 실현하기 위해 시작 항목의 플러그 인 과정을 마스터 한 다양한 실제 애플리케이션은 호환되는 Android 버전을해야

최종적으로

소스 코드를 연구, 분석하는 문제로, 그것은 자연적으로 메인 라인을 집중할 것

어떤 공공 관심사는, 더 많은 지식을 얻을
게시 48 개 원래 기사 · 원 찬양 255 · 전망 540 000 +

추천

출처blog.csdn.net/yhaolpz/article/details/105347247