(十五)Dex 加密之 Application 替换

版权声明:本文为博主原创文章,未经博主允许不得转载。
本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。

一、Application 创建流程

我们知道,当用户点击桌面上的 app 图标进行启动一个 app,是由 Zygote 进程 fork 一个子进程而来的。然后将 ActivityThread 加载到子进程中,这时候会调用 ActivityThread 中的 main 函数。我们这边从 ActivityThread 讲起。

ActivityThread 的 main

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");
        
        //准备了 Loop
        Looper.prepareMainLooper();

        //创建新的 ActivityThread,调用 attach 函数
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

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

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

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

        //与上面对应,调用   Looper.loop()
        Looper.loop();

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

ActivityThread 的 main 中调用了 ActivityThread 的 attach 方法,传递了一个 false 参数。

ActivityThread 的 attach

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ......
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            //通过 ActivityManager 获取到一个 bundle 对象
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //会调用到 
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
           ......
        } else {
          ......
        }
      ......
    }

ActivityManager.getService() 获取到的对象实际是一个 ActivityManagerProxy,调用了 ActivityManagerProxy 的 attachApplication 方法,通过 Bundle 的流程,最终会调到 ActivityManager 的 bindApplication 方法。

ActivityThread 的 bindApplication

        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) {
            ......
            sendMessage(H.BIND_APPLICATION, data);
        }

    private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }


    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

    final H mH = new H();

在 ActivityThread 的 bindApplication 最后会给 mH 发送一个 H.BIND_APPLICATION 的消息, mH 是成员变量,直接初始化,是 ActivityThread 的内部类 H, H 继承自 Handler。查找到 H 中对对应消息的处理。

H 中对 BIND_APPLICATION 的处理

                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;

H 中对 BIND_APPLICATION 的处理调用了 ActivityThread 的 handleBindApplication 这个方法,这个方法就是准备 Application 的,包括创建 Application 和创建过程中调用到 Application 中的各个方法。

ActivityThread 的 handleBindApplication

    private void handleBindApplication(AppBindData data) {
        ......

        // Allow disk access during application and provider setup. This could
        // block processing ordered broadcasts, but later processing would
        // probably end up doing the same disk access.
        Application app;
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
        try {
            // If the app is being launched for full backup or restore, bring it up in
            // a restricted environment with the base application class.
            //创建 Application
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            //对 Application 进行赋值记录
            mInitialApplication = app;

            ......
            try {
                //调用 Application 的 onCreate 方法
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                                    + ": " + e.toString(), e);
                }
            }
        ........
    }

我们先查看 app = data.info.makeApplication(data.restrictedBackupMode, null); 这个代码的实现, data.info 是一个 LoadedApk,查看 LoadedApk 的 makeApplication 方法。

LoadedApk 的 makeApplication

    public Application makeApplication(boolean forceDefaultAppClass,
                                       Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;

        //获取 AndroidManifest.xml 中配置的 Application 全类名
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            
            //我们自己的应用肯定不满足这个 if 判断
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            //创建一个 Context
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //通过反射创建 Application,同时调用 Application 的 attachBaseContext 方法
            app = mActivityThread.mInstrumentation.newApplic
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值