Proceso de la aplicación Creación de la aplicación, análisis del código fuente del proceso de inicio (Android P)

En el teléfono móvil del usuario, el inicio de una aplicación generalmente se inicia cuando el usuario hace clic en el icono en el Iniciador. ¿Dónde está el punto de partida cuando se inicia la aplicación? ¿Cómo se crea el objeto Aplicación?

A continuación, analizamos el proceso de implementación específico a través del código fuente de Android P y resolvemos nuestras dudas.

Proceso de inicio de proceso y análisis de proceso de creación de objetos de aplicación

Un sistema de aplicación inicia un comando de inicio hasta que se inicia. Su primer paso es iniciar un proceso correspondiente a una aplicación, que lleva el negocio que ejecutaremos.

Método main () de ActivityThread y método attach ()

ActivityThread es una clase muy importante en nuestro sistema Android, también representa el hilo principal correspondiente al funcionamiento de nuestra aplicación. Luego, un proceso comienza desde la función principal de la clase ActivityThread.

Ubicación del código: /frameworks/base/core/java/android/app/ActivityThread.java

Función de entrada principal

ActivityThread es una clase muy importante durante el inicio y la operación de la aplicación. El método principal de ActivityThread es el método de entrada de la aplicación, y ActivityThread representa el hilo principal o el hilo de la interfaz de usuario de la aplicación.

    public static void main(String[] args) {
        ……
        Process.setArgV0("<pre-initialized>"); //设置进程参数

        Looper.prepareMainLooper();

        ……
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        ……
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

Realizó principalmente las siguientes operaciones:

  1. Inicialice MainLooper.
  2. Cree un objeto de instancia ActivityThread y llame al método de instancia de adjuntar.
  3. Inicialice el controlador del subproceso principal y asígnelo al atributo sMainThreadHandler.
  4. El proceso principal entra en el bucle Looper.

Después de ejecutar el método principal, el proceso de la aplicación tiene un hilo principal que tiene MainLooper y ha entrado en el bucle Looper para escuchar. El objeto ActivityThread también se ha creado e inicializado en consecuencia, y el controlador del hilo principal también se ha inicializado, listo para aceptar mensajes en cualquier momento y realizar el procesamiento de mensajes.

ActivityThread constructor

Cuando se llama al constructor ActivityThread, se inicializa el objeto ResourcesManager.

    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
    }

Método de adjuntar ActivityThread

Adjuntar método de ActivityThread:

    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system; //是否是系统进程,我们的App这个值是false
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());//ApplicationThread的binder对象,用于通信
            final IActivityManager mgr = ActivityManager.getService();//获取AMS服务
            try {
                mgr.attachApplication(mAppThread, startSeq);//远程调用AMS服务的attachApplication来启动一个Application
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            // Watch for getting close to heap limit. 注册GC检测器,当可用内存较低时,清理隐藏Activity
            BinderInternal.addGcWatcher(new Runnable() {
                @Override public void run() {
                    if (!mSomeActivitiesChanged) {
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try {
                            mgr.releaseSomeActivities(mAppThread); //执行隐藏Activity栈的内存清理
                        } catch (RemoteException e) {
                            throw e.rethrowFromSystemServer();
                        }
                    }
                }
            });
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> {
            synchronized (mResourcesManager) {
                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    }
                }
            }
        };
        ViewRootImpl.addConfigCallback(configChangedCallback);
    }
Parámetro:

sistema: si es un proceso del sistema.
startSeq: el valor pasado a través de la línea de comando (PROC_START_SEQ_IDENT), el valor predeterminado es 0.

Análisis lógico:
  1. Primero detecte que la versión del proceso es un proceso del sistema, aquí nos enfocamos en procesos que no son del sistema.
  2. RuntimeInit.setApplicationObject pasa el objeto de carpeta de ApplicationThread para prepararse para la comunicación del proceso.
  3. Llame de forma remota a la aplicación del servicio AMS para iniciar una aplicación, nos centraremos en el análisis más adelante.
  4. Registre el detector GC, cuando la memoria disponible sea baja, limpie las actividades ocultas.
  5. ViewRootImpl.ConfigChangedCallback registra la supervisión del cambio de configuración.

Limpiar la pila de actividades ocultas

Primero veamos el punto 4 anterior, registre el detector GC y, cuando la memoria disponible sea baja, limpie la Actividad oculta.

Analicemos su realización técnica.

BinderInternal.addGcWatcher registra un escucha de GC para iniciar la limpieza de la pila de Actividad oculta cuando el uso de la memoria alcanza un cierto porcentaje para liberar más memoria.

¿Veamos cómo se registra este oyente GC para que surta efecto?

1. Implementación de BinderInternal

/frameworks/base/core/java/com/android/internal/os/BinderInternal.java

    static WeakReference<GcWatcher> sGcWatcher
            = new WeakReference<GcWatcher>(new GcWatcher());
    static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
    static Runnable[] sTmpWatchers = new Runnable[1];
    static long sLastGcTime;
    static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
            new BinderProxyLimitListenerDelegate();

    static final class GcWatcher {
        @Override
        protected void finalize() throws Throwable {
            handleGc();
            sLastGcTime = SystemClock.uptimeMillis();
            synchronized (sGcWatchers) {
                sTmpWatchers = sGcWatchers.toArray(sTmpWatchers);
            }
            for (int i=0; i<sTmpWatchers.length; i++) {
                if (sTmpWatchers[i] != null) {
                    sTmpWatchers[i].run();
                }
            }
            sGcWatcher = new WeakReference<GcWatcher>(new GcWatcher());
        }
    }

    public static void addGcWatcher(Runnable watcher) {
        synchronized (sGcWatchers) {
            sGcWatchers.add(watcher);
        }
    }

Análisis lógico:

Su principio se implementa utilizando el método finalize (). Los detalles son los siguientes:

  1. Primero registre un objeto GcWatcher de referencia débil, cuando el GC vuelve a mirar la referencia débil, activará su método finalize ();
  2. La matriz sTmpWatchers almacena los monitores registrados que necesitan ser procesados, es una matriz Runnable;
  3. En el método finalize (), atravesamos la matriz sTmpWatchers y llamamos al método run () del objeto Runnable para ejecutar el evento de escucha;
  4. Después de la finalización del evento de notificación, el objeto GcWatcher anterior se ha recopilado como basura, y necesitamos regenerar una entrada de monitoreo para el próximo GC.

La condición para realizar la limpieza de memoria de actividad oculta es dalvikUsed> ((3 * dalvikMax) / 4), es decir, cuando la memoria utilizada actualmente es mayor que 3/4 de la memoria total, se cumplen las condiciones de ejecución.

La limpieza se realiza mediante el método releaseSomeActivities de AMS.

2. releaseSomeActivities 方法

Método releaseSomeActivities de ActivityManagerService:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @Override
    public void releaseSomeActivities(IApplicationThread appInt) {
        synchronized(this) {
            final long origId = Binder.clearCallingIdentity();
            try {
                ProcessRecord app = getRecordForAppLocked(appInt); //从最近运行App列表中找到对应的ProcessRecord对象
                mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem"); //执行隐藏Activity栈的清理工作
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

El método de instancia releaseSomeActivitiesLocked de ActivityStackSupervisor se llama aquí para realizar la operación de la pila de trabajo de Activity.

Ubicación del código: frameworks / base / services / core / java / com / android / server / am / ActivityStackSupervisor.java

Reglas de reciclaje:
  1. Para una aplicación de pila única (TaskRecord), todas las interfaces no se reciclarán en primer plano, solo en el caso de varias pilas, el sistema reciclará la actividad de la pila invisible.
  2. ActivityStack usa maxTasks para garantizar que se eliminen como máximo tareas.size () / 4 y se borre al menos un TaskRecord.

Método attachApplication () de ActivityManagerService

El método attachApplication () de ActivityManagerService es la lógica central creada por Process Application. Analicemos su proceso de implementación.

El método de conexión de ActivityThread, llame de forma remota a attachApplication del servicio AMS para iniciar una aplicación, el parámetro aquí es una instancia de ApplicationThread, la clase ApplicationThread es una clase interna de ActivityThread, responsable de la comunicación de Binder con servicios como AMS

    @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }

El método attachApplicationLocked se llama aquí:

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {

        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        ProcessRecord app;
        ……
        //获取进程所对应的ProcessRecord对象。
        if (app == null) {
            ……
            //获取失败,退出进程
            return false;
        }

        // If this application record is still attached to a previous
        // process, clean it up now.
        if (app.thread != null) {//如果该ProcessRecord对象之前attached到了一个进程,则进行清理操作
            handleAppDiedLocked(app, true, true);
        }
        ……
        final String processName = app.processName;
        ……
        //注册Binder死亡监听
        ……
        //以下进行ProcessRecord对象的相关初始化操作
        app.makeActive(thread, mProcessStats);//绑定ApplicationThread对象
        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;//进程优先级设置
        app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        app.forcingToImportant = null;
        updateProcessForegroundLocked(app, false, false);//前台服务相关设置
        app.hasShownUi = false;
        app.debugging = false;
        app.cached = false;
        app.killedByAm = false;
        app.killed = false;


        // We carefully use the same state that PackageManager uses for
        // filtering, since we use this flag to decide if we need to install
        // providers when user is unlocked later
        app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);

        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        ……
        provider相关处理
        ……
        ……
        try {
            ……
            ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
            app.compat = compatibilityInfoForPackageLocked(appInfo);

            ……

            //Build.SERIAL获取,Android P以下可以获取到

            ……
            //Instrumentation处理,多进程的使用同一个Instrumentation(后续进程并入第一个进程)。

            ……
            if (app.isolatedEntryPoint != null) {
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
            } else if (app.instr != null) {//Instrumentation不为空
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, isAutofillCompatEnabled);
            } else {
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, isAutofillCompatEnabled);
            }
            ……
            checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
            updateLruProcessLocked(app, false, null);
            checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            ……
            return false;
        }

        // 从正在启动进程列表删除
        mPersistentStartingProcesses.remove(app);
        ……
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {//查看顶部可展示Activity是否正在等待在当前进程中运行。也就是处理Activity展示
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        // Find any services that should be running in this process...
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName); //处理需要运行在当前进程中的Service
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

        // Check if a next-broadcast receiver is in this process...
        //处理需要运行在当前进程中的broadcast receiver
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
                didSomething |= sendPendingBroadcastsLocked(app);
                checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
            } catch (Exception e) {
                // If the app died trying to launch the receiver we declare it 'bad'
                Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                badApp = true;
            }
        }

        ……

        if (!didSomething) {
            updateOomAdjLocked();
            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
        }

        return true;
    }      
            
Análisis lógico:
  1. Obtenga el objeto ProcessRecord correspondiente al proceso.
  2. Regístrese para el monitoreo de la muerte de Binder
  3. Realizar operaciones de inicialización relacionadas con el objeto ProcessRecord
  4. Procesamiento de instrumentación, varios procesos utilizan la misma instrumentación (los procesos posteriores se fusionan en el primer proceso).
  5. Llame a thread.bindApplication para iniciar realmente la aplicación. Aquí está el proceso de inicio de la aplicación.
  6. Manejar pantalla de actividad, servicio, BroadcastReceiver, etc. Esto implica el proceso de activación de la Actividad, lo analizaremos más adelante.

Llame a mStackSupervisor.attachApplicationLocked (aplicación) para iniciar la página Actividad en la pila de Actividades que debe mostrarse.

La llamada al método thread.bindApplication aquí es donde realmente se crea el objeto Aplicación, centrémonos en él.

Inicio de la aplicación

El método attachApplicationLocked en ActivityManagerService en el proceso AMS del servicio, llama de forma remota la aplicación bindApplication del ApplicationThread del proceso actual para crear e iniciar la aplicación correspondiente a la aplicación.

ApplicationThread hereda de IApplicationThread.Stub, lo que también demuestra que su función importante es realizar la comunicación Binder entre AMS y el Cliente.

Método bindApplication de ApplicationThread

Método de aplicación:
/frameworks/base/core/java/android/app/ActivityThread.java

        public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, 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, boolean autofillCompatibilityEnabled) {

            if (services != null) {
                …… 调试日志
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);

            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableBinderTracking = enableBinderTracking;
            data.trackAllocation = trackAllocation;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            data.buildSerial = buildSerial;
            data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
            sendMessage(H.BIND_APPLICATION, data);
        }
Análisis lógico:
  • Los servicios guardan algunos servicios básicos del sistema, aquí llame al método initServiceCache de ServiceManager, agregue estos servicios de Serivce a la lista de caché "sCache" en SM
  • Genere el objeto AppBindData y establezca la información de inicialización de la aplicación.
  • Envíe el mensaje BIND_APPLICATION para continuar procesando.

Método handleBindApplication de ActivityThread

HandleMessage de H procesa el mensaje BIND_APPLICATION:

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    
        }

Aquí llame directamente al método handleBindApplication para iniciar formalmente el proceso de Aplicación.

handleBindApplication :

    private void handleBindApplication(AppBindData data) {
        ……

        mBoundApplication = data;//mBoundApplication赋值
        ……
        Process.setArgV0(data.processName);//设置进程名称
        android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                UserHandle.myUserId());
        VMRuntime.setProcessPackageName(data.appInfo.packageName);//设置相关包名

        ……
        //解码Bitmap使用的规则,Android P之前使用BitmapFactory,之后使用ImageDecoder
        ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;

        //重置系统时区
        TimeZone.setDefault(null);
        ……

        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//生成LoadedApk对象

        ……

        // 设置Build的SERIAL属性值
        try {
            Field field = Build.class.getDeclaredField("SERIAL");
            field.setAccessible(true);
            field.set(Build.class, data.buildSerial);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            /* ignore */
        }

        ……
        //debug相关设置
        ……
        //设置Instrumentation
        ……
        //创建appContext对象
        ……
        if (ii != null) {
            ……
            //创建Instrumentation对象,并执行init初始化
            final ComponentName component = new ComponentName(ii.packageName, ii.name);
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

            ……
        } else {
            mInstrumentation = new Instrumentation();
            mInstrumentation.basicInit(this);
        }

        ……
        // 在进程启动过程中或Provider安装过程中,暂时允许访问磁盘权限
        Application app;
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
        try {
            // 创建Application对象
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            ……
            mInitialApplication = app;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {//如果应用正在安装或恢复这类特殊状态,restrictedBackupMode值为true。这里正常情况下为false
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers); //此处安装ContentProvider
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            // 在providers安装之后,执行Instrumentation对象的onCreate方法,启动Instrumentation线程
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            ……
            try {
                mInstrumentation.callApplicationOnCreate(app);//通过callApplicationOnCreate,调用Application对象的onCreate方法
            }
            ……
        } finally {
            ……
        }
        ……
        // 预加载字体资源相关处理
        
    }
Análisis lógico

Este método tiene mucha lógica, veamos qué procesamiento realiza principalmente:

  1. Establezca mBoundApplication = data (parámetro AppBindData object).
  2. Process.setArgV0 (data.processName) establece el nombre del proceso.
  3. VMRuntime.setProcessPackageName (data.appInfo.packageName) 设置 包 名。
  4. Establezca las reglas para decodificar Bitmap.
  5. Restablecer la zona horaria del sistema.
  6. Generar objeto LoadedApk.
  7. Establezca el valor del atributo SERIAL de Build.
  8. Configurar instrumentación.
  9. Crea un objeto appContext.
  10. Cree un objeto de Instrumentación e inicialícelo.
  11. Durante el inicio del proceso o el proceso de instalación del proveedor, configure el indicador de permiso para permitir temporalmente el acceso al disco.
  12. Crear un objeto de aplicación.
  13. Instalar ContentProvider.
  14. Después de instalar los proveedores, ejecute el método onCreate del objeto Instrumentation para iniciar el hilo de Instrumentation.
  15. Llame al método onCreate del objeto Aplicación a través de callApplicationOnCreate del objeto Instrumentation.
  16. Precarga de procesamiento relacionado con recursos de fuentes.

Después de ejecutar el método handleBindApplication, se iniciará nuestra aplicación.

El proceso de creación de un objeto Aplicación es muy importante, y lo analizamos en detalle.

Creación de objeto de aplicación

En el método handleBindApplicaiton del objeto ActivityThread, se crea el objeto Aplicación, el código:

// 创建Application对象
app = data.info.makeApplication(data.restrictedBackupMode, null);

Aquí los datos son un objeto AppBindData, y su propiedad de información es un objeto LoadedApk, por lo que sabemos que el método makeApplicaiton del objeto LoadedApk se llama realmente aquí.

Método MakeApplication de la clase LoadedApk

/frameworks/base/core/java/android/app/LoadedApk.java

    public Application makeApplication(boolean forceDefaultAppClass, //如果应用正在安装或恢复这类特殊状态,restrictedBackupMode值(这里是第一个参数)为true,正常启动应用,这里是false。
            Instrumentation instrumentation) { //instrumentation参数这里传递进来的是null
        if (mApplication != null) { //已经存在,直接返回
            return mApplication;
        }
        ……
        Application app = null;
        //设置正在启动的App的Application的类名
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            //创建并处理ClassLoader对象
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            //创建ContextImpl对象作为application的Context环境
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //这里调用Instrumentation对象的newApplication方法来创建Application对象。
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app); //ContextImpl对象绑定Application对象
        } 
        ……
        mActivityThread.mAllApplications.add(app); //添加到mAllApplications列表
        mApplication = app;

        if (instrumentation != null) { //这里在App启动过程中传递进来的是null,不会走此逻辑
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }
        ……
        // Rewrite the R 'constants' for all library apks.
        ……

        return app;
    }
Análisis lógico:
  1. Si se ha asignado una aplicación, vuelva directamente, de lo contrario continúe.
  2. Establezca el nombre de la clase de aplicación de la aplicación que se está iniciando.
  3. Crear y procesar objetos de ClassLoader.
  4. Cree un objeto ContextImpl como el entorno Context de la aplicación.
  5. Llame al método newApplication del objeto Instrumentation para crear el objeto Aplicación, donde el objeto Instrumentation se obtiene a través de ActivityThread.
  6. El objeto ContextImpl está vinculado al objeto Aplicación.
  7. Agregar a la lista de mAllApplications.

Continúe viendo que thread.bindApplication realmente inicia el método de aplicación.

Nuevo método de aplicación de la clase Instrumentation

La creación del objeto Aplicación se crea en última instancia por reflexión en el nuevo método de Aplicación del objeto Instrumentación.

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }
    
    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }
Análisis lógico:
  1. Primero, cargue el nombre de clase correspondiente a la Aplicación a través del objeto ClassLoader.
  2. Utilice la llamada de reflexión Java, newInstance, un objeto de aplicación.
  3. Finalmente, llame al método de conexión del objeto Aplicación, el parámetro es el contexto. Aquí está el método de conexión de la aplicación con la que estamos familiarizados, podemos manejar algunos trabajos de inicialización cuando se inicia la aplicación.

En este punto, el proceso de creación y puesta en marcha de nuestra Aplicación ha sido analizado y completado, y también tendrá una comprensión más clara de esto en detalle. Todo el proceso involucra el lado del Cliente donde se encuentra nuestra aplicación y el lado del Servidor representado por ActivityManagerService. El proceso de comunicación entre ellos, por supuesto, se basa en Binder. ApplicationThread sirve como referencia para que el servidor llame al cliente y se da cuenta de la comunicación entre ellos.

Publicado 9 artículos originales · me gusta 0 · vistas 3226

Supongo que te gusta

Origin blog.csdn.net/u011578734/article/details/105654761
Recomendado
Clasificación