App启动——Application的创建

Application的创建

一个 app 启动时候创建一个 Application 对象。这个对象的创建时间在 frameworks 中调用创建的,创建流程可见下图,涉及的几个主要的类调用。

Application创建流程

一、主线程运行入口

​ APP进程起来后,主线程运行入库 ActivityThread.main() 方法。

    ```java
    // ActivityThread.java
    
    @UnsupportedAppUsage
    final ApplicationThread mAppThread = new ApplicationThread();
    
    public static void main(String[] args) {
    	// ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        // ...
    }
    
    @UnsupportedAppUsage
    private void attach(boolean system, long startSeq) {
        // ...
    
        if (!system) {
            // ...
    
            final IActivityManager mgr = ActivityManager.getService(); //获取 IActivityManager 对象。
            try {
                mgr.attachApplication(mAppThread, startSeq); // Binder 调用 AMS 的 attachApplicaion() 方法。
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
    		// ...
        }
    
        // ...
    }
    ```

运行启动是一般的app,并非 system app,因此进入到 if 分支。

二、ActivityManagerService 方法执行

从app主线程执行,进而跨进程调用到 ActivityManagerServiceattachApplication(IApplicationThread thread, long startSeq) 方法。

// ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

@GuardedBy("this")
private void attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
	// ......  这里的一个比较重要的数据是 appInfo:ApplicationInfo
    // if 分支内,表明运行的时候隔离状态的app,这样的app不能访问系统资源,服务及其他app进程。
    if (app.getIsolatedEntryPoint() != null) {
        // This is an isolated process which should just call an entry point instead of
        // being bound to an application.
        thread.runIsolatedEntryPoint(
                app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
    } else if (instr2 != null) {
        thread.bindApplication(processName, appInfo,
                app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                providerList,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.getCompat(), getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.getDisabledCompatChanges(), serializedSystemFontMap,
                app.getStartElapsedTime(), app.getStartUptime());
    } else {
        thread.bindApplication(processName, appInfo,
                app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                providerList, null, profilerInfo, null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.getCompat(), getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.getDisabledCompatChanges(), serializedSystemFontMap,
                app.getStartElapsedTime(), app.getStartUptime());
    }
	// ......
}

在内部调用到 attachApplicationLocked() 方法,在方法内部,会执行到 bindApplication() 方法,除非运行的app是一个独立APP,即不访问系统任何资源。这个方法里还有一个重要的数据变量是 appInfo 表示了应用的信息,会在调用 bindApplication() 方法时传递给 ApplicationThread 对象方法。

三、ApplicationThread.bindApplication()

// ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public final void bindApplication(String processName, ApplicationInfo appInfo,
            String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
            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,
            SharedMemory serializedSystemFontMap,
            long startRequestedElapsedTime, long startRequestedUptime) {
        // ......
        
            AppBindData data = new AppBindData();
            // 构建 AppBindData 数据结构。
            updateCompatOverrideScale(compatInfo);
            CompatibilityInfo.applyOverrideScaleIfNeeded(config);
            sendMessage(H.BIND_APPLICATION, data);  // 发送消息。
    }
}

ActivityManagerService 中进行执行后,获取必要的信息,然后执行回到 ApplicationThread 的 app 进程 bindApplication() 方法中,并构建 AppBindData 数据对象,最终发送消息 H.BIND_APPLICATION 进入消息队列等待执行。

四、handleBindApplication(AppBindData data)

通过消息机制执行到 handleMessage(Message msg),依据消息 whatBIND_APPLICATION 执行方法 handleBindApplication(AppBindData data)

// ActivityThread.java

@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
	// ...
    // 获取 LoadedApk 类型对象 
    data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,  
    							false /* securityViolation */, true /* includeCode */,
    							false /* registerPackage */, isSdkSandbox);
    
    // ...
    // 获取 ActivityManagerService 的 Binder 句柄
    final IActivityManager mgr = ActivityManager.getService();   
    // 创建 Context 上下文对象
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);    
    
    // ...
    Application app;
    // ...
        try {
			// 通过 LoadedApk 对象创建 Application 对象,内部具体实现细节,并且调用到了 Application.attach(Coext)。
		    // 在 attach(Context) 方法内调用从 ContextWrapper 继承而来的 attachBaseContext(Context),设置 mBaseContext 的实例变量。 
            app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
            // ...
        } finally {
            // ...
        }
		// ...
        try {
            mgr.finishAttachApplication(mStartSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
}

执行 handleBindApplication() 方法传入参数 AppBindData ,在最终创建 Application 前,data.info 被赋值 。接着调用到 LoadedApk.makeApplicationInner(boolean forceDefaultAppClass, Instrumentation instrumentation)

// LoadedApk.java

public Application makeApplicationInner(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    return makeApplicationInner(forceDefaultAppClass, instrumentation,
            /* allowDuplicateInstances= */ false);
}

private Application makeApplicationInner(boolean forceDefaultAppClass,
        Instrumentation instrumentation, boolean allowDuplicateInstances) {
    if (mApplication != null) {
        return mApplication;
    }

	// ...
    Application app = null;

    final String myProcessName = Process.myProcessName();
    String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
            myProcessName);
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        final java.lang.ClassLoader cl = getClassLoader();
		// ...
        // 创建方式与 ActivityThread 中 handleBindApplication 创建方式一致。
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); 
 		// ...
        // 创建 Application
        app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
		// ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;
	// ...
    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app); // 调用了 Application 的声明周期方法 onCreate
        } catch (Exception e) {
           // ...
        }
    }
    return app;
}

最终调用的 Application 对象是在 Instrumentation 中创建。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VoidHope

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值