análisis de código fuente 10 startActivity Android

Fuente basado en Android 10

Android 10.0 startActivity diagrama de flujo

Esta cifra se centra en el perfeccionamiento de algunos de su ciclo de vida, Android 10 añade un ActivityTaskManager, diseñado para gestionar la actividad, se hizo cargo de parte de la obra de ActivityManager

comprender Instrumentación

Actividad viajará primero a través de llamar Instrumentación, Instrumentación contiene callActivityOnCreate, callActivityOnPause, callApplicationOnCreate y otras llamadas, con una potente actividad de seguimiento y el ciclo de vida de las aplicaciones, también se utiliza como base para la aplicación de pruebas de marco para su uso. Un proceso tiene una objetos ActivityThread, objeto contiene objetos un ActivityThread Instrumentación, cada actividad son en posesión de Instrumentación

IPC suceda Dónde?

En la Instrumentación entrar a través de la interfaz desde el proceso App IActivityTaskManager.aidl a proceso system_server; proceso Volver App por el system_server por la interfaz IApplicationThread.aidl en ClientTransaction

La actividad es cómo manejar la pila?

ActivityRecord: Actividad ActivityRecord forma de grabar un ActivityRecord corresponde a una instancia de actividad
TaskRecord: Esta es una pila real de actividad tiene un ArrayList interno <ActivityRecord>, la pila actual registra toda la actividad
ActivityStack: La actividad es responsable de la gestión de la pila, multi-tienda un TaskRecord

La actividad en el nodo donde leer el manifiesto de configuración del modo de arranque

Lectura de la configuración de la figura manifiesto

Figura devuelto por PackageManagerService # resolveIntentInternal método ResolveInfo, ResolveInfo incluyendo ActivityInfo, ServiceInfo, ProviderInfo y otra información, esta llamada ya está en el system_server proceso, por lo que no es del IPC, PackageManagerService principalmente responsable de analizar AndroidManifest.xml, apk directorio local de exploración, eliminar la instalación de aplicaciones de gestión espera

Donde detectar la actividad se ha registrado en el manifiesto?

Los principales métodos código 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 es ActivityInfo, y se devuelve ActivityInfo causa vacío error posterior. Eso es AINFO viene? Por supuesto, se analiza por el método PackageManagerService # resolveIntentInternal. Entonces detectado método Instrumentación # checkStartActivityResult al valor de retorno después de ActivityManager.START_CLASS_NOT_FOUND, tirar "No se pudo encontrar la clase de actividad explícita {xxx} ;? Se ha declarado en esta actividad en su AndroidManifest.xml" anomalía

¿Por qué no tener efecto configurado individualmente taskAffinity

La clave de código ActivityStarter # startActivityUnchecked métodos:

  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();
  }

Sólo mLaunchFlags marcado FLAG_ACTIVITY_NEW_TASK irá a crear una nueva pila de actividad que se TaskRecord, y el sistema no hizo un trato con la situación por sí sola configuración de taskAffinity. Eso launchMode configurado en AndroidManifest.xml es donde el proceso, y en respuesta a mLaunchFlags que?
Método # ActivityStarter startActivityUnchecked llamada ActivityStarter # computeLaunchingTaskFlags método configurado mLaunchFlags código es el siguiente:

   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;
    }

Se puede ver de modo LAUNCH_SINGLE_INSTANCE se inicia en una nueva pila y por lo que ya son conocidas reglas

Comprensión y ClientTransactionItem ActivityLifecycleItem

ClientLifecycleManager uno o más eventos del ciclo de vida pueden ser agrupados juntos como es ClientTransaction para ejecutar una transacción, nueva actividad onCreate cuando startActivity, onStart, se ejecuta evento onResume se almacena en una transacción

Nueva actividad onCreate caso de startActivity cuando se almacena en una variable miembro de ClientTransaction Lista <ClientTransactionItem> tipo, el vehículo es LaunchActivityItem. LaunchActivityItem también ClientTransactionItem sub-categorías, a saber comenzar Sucesos de actividad. Otra NewIntentItem (callback gatillo onNewIntent), ActivityResultItem (onActivityResult trigger), ConfigurationChangeItem (onConfigurationChanged de devolución de llamada de activación) y otros eventos

Cuando startActivity nueva actividad de los acontecimientos onResume almacena en la variable de variables miembro de tipo ClientTransaction ActivityLifecycleItem, esta variable también representa el estado final del ciclo de vida del portador es ResumeActivityItem. ActivityLifecycleItem también ClientTransactionItem de una subclase

¿Por qué no hacer la operación que consume tiempo onPause método Actividad en?

ClientTransaction es datos parcelable, enviados al terminal por el método de scheduleTransaction App IApplicationThread.aidl, y después se añadió a la cola principal mensaje ActivityThread.H hilo para su ejecución. El primero, a su vez envía una nueva Actividad Actividad de la pausa y reanudar la operación, y luego sucede tanto las transacciones en este orden por el tiempo ActivityThread.H startActivity, no podemos hacer mucho tiempo el funcionamiento onPause método de actividad, ya que sólo después de que el método de aplicación onPause eventos del ciclo de vida siguiente actividad con el fin de ser ejecutado, de lo contrario bloquean las nuevas pantallas de interfaz

instancia de actividad donde se crea?

En ActivityThread el método # performLaunchActivity creará una instancia de un objeto de actividad por el método de Instrumentación # newActivity, posteriormente llamado método onCreate método Instrumentación # callActivityOnCreate de la actividad de devolución de llamada

Haga clic en el icono para iniciar el menú de aplicaciones

Lanzador, haga clic en el icono para comenzar es llamar al mismo método startActivity, pero hay que crear un proceso, el código clave en métodos 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);

diagrama de flujo StartProcess

la comunicación de procesos cigoto y adoptado una forma zócalo, por qué no usar un mundo más seguro, sólo tiene que copiar los datos una vez que de ligante? Como un proceso fertilizado cigoto Android, el proceso creado por el método de tenedor, mientras que tenedor multi-roscado no está permitido, o porque los mecanismos de Copy-on-Write resultar en un callejón sin salida, y el aglutinante se basa en la ejecución de subprocesos múltiples

En el método PROCESSLIST # startProcessLocked, pasando el valor "android.app.ActivityThread" de los parámetros del punto de entrada, el seguimiento pasará a través del proceso de cigoto, el nuevo proceso cigoto tenedor tenga éxito, ActivityThread función principal # se llamará el nuevo proceso, a saber, entrada de inicio real de aplicación

diagrama de flujo ActivityThread.main

En ActivityManagerService # attachApplicationLocked método de ejecución en dos lógica clave, para crear Ejemplos de aplicación En primer lugar Volver de la aplicación y el proceso de devolución de llamada por el método IApplicationThread onCreate; el segundo es llamar al método ActivityTaskManagerService # attachApplication, más que empezar Inicio de Actividades.
Actividad de inicio y startActivity ordinaria mismo, serán llamados a método ActivityStackSupervisor # realStartActivityLocked

Comprensión y ActivityThread ApplicationThread

método ActivityThread.main () es para iniciar el procedimiento de entrada, el hilo principal inicializa Looper, el procesamiento de mensajes en la ActivityThread.H. ApplicationThread es de clase interna ActivityThread que implementa la interfaz para recibir las devoluciones de llamada sistemas y servicios IApplicationThread.aidl AMS, y la mayoría de ellos están relacionados con las tareas de los cuatro componentes, se envía un mensaje al controlador de ActivityThread.H, es decir, el cambio de aglutinante para el hilo principal procesamiento de hilo

Cómo iniciar una actividad no registrada en el manifiesto?

Cargar la información del manifiesto y pruebas en proceso de registro system_server, no puede interferir con la lógica de detección. Es una práctica común en el manifiesto se registra una actividad de marcador de posición, proceso system_server antes de entrar en la Actividad Actividad no registrada modificar el marcador de posición, y luego esperar a que el proceso de regreso de system_server luego cambia de nuevo a la aplicación actividad no está registrado, y luego para crear, inicio , que se necesita para conectar dos:

enganchar 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);

enganchar 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 继续处理
 }
});

Actividad no registrado empiezan a darse cuenta de la premisa debe ser startActivity han dominado el proceso, que es el conector de entrada, las diversas aplicaciones prácticas tienen que ser compatibles versión de Android

finalmente

Con un problema de analizar, estudiar el código fuente, que, naturalmente, enfocar la línea principal

No hay preocupación pública, obtener más conocimiento
Publicado 48 artículos originales · ganado elogios 255 · vistas 540 000 +

Supongo que te gusta

Origin blog.csdn.net/yhaolpz/article/details/105347247
Recomendado
Clasificación