// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.incrementalinstall;

import android.app.Application;
import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.util.Log;

import dalvik.system.DexFile;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Map;

/**
 * An Application that replaces itself with another Application (as defined in
 * an AndroidManifext.xml meta-data tag). It loads the other application only
 * after side-loading its .so and .dex files from /data/local/tmp.
 *
 * This class is highly dependent on the private implementation details of
 * Android's ActivityThread.java. However, it has been tested to work with
 * JellyBean through Marshmallow.
 */
public final class BootstrapApplication extends Application {
    private static final String TAG = "incrementalinstall";
    private static final String MANAGED_DIR_PREFIX = "/data/local/tmp/incremental-app-";
    private static final String REAL_APP_META_DATA_NAME = "incremental-install-real-app";
    private static final String REAL_INSTRUMENTATION_META_DATA_NAME0 =
            "incremental-install-real-instrumentation-0";
    private static final String REAL_INSTRUMENTATION_META_DATA_NAME1 =
            "incremental-install-real-instrumentation-1";

    private ClassLoaderPatcher mClassLoaderPatcher;
    private Application mRealApplication;
    private Instrumentation mOrigInstrumentation;
    private Instrumentation mRealInstrumentation;
    private Object mStashedProviderList;
    private Object mActivityThread;
    public static DexFile[] sIncrementalDexFiles; // Needed by junit test runner.

    @Override
    protected void attachBaseContext(Context context) {
        super.attachBaseContext(context);
        try {
            mActivityThread = Reflect.invokeMethod(Class.forName("android.app.ActivityThread"),
                    "currentActivityThread");
            mClassLoaderPatcher = new ClassLoaderPatcher(context);

            mOrigInstrumentation =
                    (Instrumentation) Reflect.getField(mActivityThread, "mInstrumentation");
            Context instContext = mOrigInstrumentation.getContext();
            if (instContext == null) {
                instContext = context;
            }

            // When running with an instrumentation that lives in a different package from the
            // application, we must load the dex files and native libraries from both pacakges.
            // This logic likely won't work when the instrumentation is incremental, but the app is
            // non-incremental. This configuration isn't used right now though.
            String appPackageName = getPackageName();
            String instPackageName = instContext.getPackageName();
            boolean instPackageNameDiffers = !appPackageName.equals(instPackageName);
            Log.i(TAG, "App PackageName: " + appPackageName);
            if (instPackageNameDiffers) {
                Log.i(TAG, "Inst PackageName: " + instPackageName);
            }

            File appIncrementalRootDir = new File(MANAGED_DIR_PREFIX + appPackageName);
            File appLibDir = new File(appIncrementalRootDir, "lib");
            File appDexDir = new File(appIncrementalRootDir, "dex");
            File appInstallLockFile = new File(appIncrementalRootDir, "install.lock");
            File appFirstRunLockFile = new File(appIncrementalRootDir, "firstrun.lock");
            File instIncrementalRootDir = new File(MANAGED_DIR_PREFIX + instPackageName);
            File instLibDir = new File(instIncrementalRootDir, "lib");
            File instDexDir = new File(instIncrementalRootDir, "dex");
            File instInstallLockFile = new File(instIncrementalRootDir, "install.lock");
            File instFirstRunLockFile = new File(instIncrementalRootDir, "firstrun.lock");

            boolean isFirstRun = LockFile.installerLockExists(appFirstRunLockFile)
                    || (instPackageNameDiffers
                               && LockFile.installerLockExists(instFirstRunLockFile));
            if (isFirstRun) {
                if (mClassLoaderPatcher.mIsPrimaryProcess) {
                    // Wait for incremental_install.py to finish.
                    LockFile.waitForInstallerLock(appInstallLockFile, 30 * 1000);
                    LockFile.waitForInstallerLock(instInstallLockFile, 30 * 1000);
                } else {
                    // Wait for the browser process to create the optimized dex files
                    // and copy the library files.
                    LockFile.waitForInstallerLock(appFirstRunLockFile, 60 * 1000);
                    LockFile.waitForInstallerLock(instFirstRunLockFile, 60 * 1000);
                }
            }

            mClassLoaderPatcher.importNativeLibs(instLibDir);
            sIncrementalDexFiles = mClassLoaderPatcher.loadDexFiles(instDexDir, instPackageName);
            if (instPackageNameDiffers) {
                mClassLoaderPatcher.importNativeLibs(appLibDir);
                mClassLoaderPatcher.loadDexFiles(appDexDir, appPackageName);
            }

            if (isFirstRun && mClassLoaderPatcher.mIsPrimaryProcess) {
                LockFile.clearInstallerLock(appFirstRunLockFile);
                if (instPackageNameDiffers) {
                    LockFile.clearInstallerLock(instFirstRunLockFile);
                }
            }

            // mInstrumentationAppDir is one of a set of fields that is initialized only when
            // instrumentation is active.
            if (Reflect.getField(mActivityThread, "mInstrumentationAppDir") != null) {
                String metaDataName = REAL_INSTRUMENTATION_META_DATA_NAME0;
                if (mOrigInstrumentation instanceof SecondInstrumentation) {
                    metaDataName = REAL_INSTRUMENTATION_META_DATA_NAME1;
                }
                mRealInstrumentation =
                        initInstrumentation(getClassNameFromMetadata(metaDataName, instContext));
            } else {
                Log.i(TAG, "No instrumentation active.");
            }

            // Even when instrumentation is not enabled, ActivityThread uses a default
            // Instrumentation instance internally. We hook it here in order to hook into the
            // call to Instrumentation.onCreate().
            BootstrapInstrumentation bootstrapInstrumentation = new BootstrapInstrumentation(this);
            populateInstrumenationFields(bootstrapInstrumentation);
            Reflect.setField(mActivityThread, "mInstrumentation", bootstrapInstrumentation);

            // attachBaseContext() is called from ActivityThread#handleBindApplication() and
            // Application#mApplication is changed right after we return. Thus, we cannot swap
            // the Application instances until onCreate() is called.
            String realApplicationName = getClassNameFromMetadata(REAL_APP_META_DATA_NAME, context);
            Log.i(TAG, "Instantiating " + realApplicationName);
            Instrumentation anyInstrumentation =
                    mRealInstrumentation != null ? mRealInstrumentation : mOrigInstrumentation;
            mRealApplication = anyInstrumentation.newApplication(
                    getClassLoader(), realApplicationName, context);

            // Between attachBaseContext() and onCreate(), ActivityThread tries to instantiate
            // all ContentProviders. The ContentProviders break without the correct Application
            // class being installed, so temporarily pretend there are no providers, and then
            // instantiate them explicitly within onCreate().
            disableContentProviders();
            Log.i(TAG, "Waiting for Instrumentation.onCreate");
        } catch (Exception e) {
            throw new RuntimeException("Incremental install failed.", e);
        }
    }

    /**
     * Returns the fully-qualified class name for the given key, stored in a
     * &lt;meta&gt; witin the manifest.
     */
    private static String getClassNameFromMetadata(String key, Context context)
            throws NameNotFoundException {
        String pkgName = context.getPackageName();
        ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(pkgName,
                PackageManager.GET_META_DATA);
        String value = appInfo.metaData.getString(key);
        if (value != null && !value.contains(".")) {
            value = pkgName + "." + value;
        }
        return value;
    }

    /**
     * Instantiates and initializes mRealInstrumentation (the real Instrumentation class).
     */
    private Instrumentation initInstrumentation(String realInstrumentationName)
            throws ReflectiveOperationException {
        if (realInstrumentationName == null) {
            // This is the case when an incremental app is used as a target for an instrumentation
            // test. In this case, ActivityThread can instantiate the proper class just fine since
            // it exists within the test apk (as opposed to the incremental apk-under-test).
            Log.i(TAG, "Running with external instrumentation");
            return null;
        }
        // For unit tests, the instrumentation class is replaced in the manifest by a build step
        // because ActivityThread tries to instantiate it before we get a chance to load the
        // incremental dex files.
        Log.i(TAG, "Instantiating instrumentation " + realInstrumentationName);
        Instrumentation ret =
                (Instrumentation) Reflect.newInstance(Class.forName(realInstrumentationName));
        populateInstrumenationFields(ret);
        return ret;
    }

    /**
     * Sets important fields on a newly created Instrumentation object by copying them from the
     * original Instrumentation instance.
     */
    private void populateInstrumenationFields(Instrumentation target)
            throws ReflectiveOperationException {
        // Initialize the fields that are set by Instrumentation.init().
        String[] initFields = {"mAppContext", "mComponent", "mInstrContext", "mMessageQueue",
                "mThread", "mUiAutomationConnection", "mWatcher"};
        for (String fieldName : initFields) {
            Reflect.setField(target, fieldName, Reflect.getField(mOrigInstrumentation, fieldName));
        }
    }

    /**
     * Called by BootstrapInstrumentation from Instrumentation.onCreate().
     * This happens regardless of whether or not instrumentation is enabled.
     */
    void onInstrumentationCreate(Bundle arguments) {
        Log.i(TAG, "Instrumentation.onCreate() called. Swapping references.");
        try {
            swapApplicationReferences();
            enableContentProviders();
            if (mRealInstrumentation != null) {
                Reflect.setField(mActivityThread, "mInstrumentation", mRealInstrumentation);
                mRealInstrumentation.onCreate(arguments);
            }
        } catch (Exception e) {
            throw new RuntimeException("Incremental install failed.", e);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        try {
            Log.i(TAG, "Application.onCreate() called.");
            mRealApplication.onCreate();
        } catch (Exception e) {
            throw new RuntimeException("Incremental install failed.", e);
        }
    }

    /**
     * Nulls out ActivityThread.mBoundApplication.providers.
     */
    private void disableContentProviders() throws ReflectiveOperationException {
        Object data = Reflect.getField(mActivityThread, "mBoundApplication");
        mStashedProviderList = Reflect.getField(data, "providers");
        Reflect.setField(data, "providers", null);
    }

    /**
     * Restores the value of ActivityThread.mBoundApplication.providers, and invokes
     * ActivityThread#installContentProviders().
     */
    private void enableContentProviders() throws ReflectiveOperationException {
        Object data = Reflect.getField(mActivityThread, "mBoundApplication");
        Reflect.setField(data, "providers", mStashedProviderList);
        if (mStashedProviderList != null && mClassLoaderPatcher.mIsPrimaryProcess) {
            Log.i(TAG, "Instantiating content providers");
            Reflect.invokeMethod(mActivityThread, "installContentProviders", mRealApplication,
                    mStashedProviderList);
        }
        mStashedProviderList = null;
    }

    /**
     * Changes all fields within framework classes that have stored an reference to this
     * BootstrapApplication to instead store references to mRealApplication.
     */
    @SuppressWarnings("unchecked")
    private void swapApplicationReferences() throws ReflectiveOperationException {
        if (Reflect.getField(mActivityThread, "mInitialApplication") == this) {
            Reflect.setField(mActivityThread, "mInitialApplication", mRealApplication);
        }

        List<Application> allApplications =
                (List<Application>) Reflect.getField(mActivityThread, "mAllApplications");
        for (int i = 0; i < allApplications.size(); i++) {
            if (allApplications.get(i) == this) {
                allApplications.set(i, mRealApplication);
            }
        }

        // Contains a reference to BootstrapApplication and will cause BroadCastReceivers to fail
        // if not replaced.
        Context contextImpl = mRealApplication.getBaseContext();
        Reflect.setField(contextImpl, "mOuterContext", mRealApplication);

        for (String fieldName : new String[] {"mPackages", "mResourcePackages"}) {
            Map<String, WeakReference<?>> packageMap =
                    (Map<String, WeakReference<?>>) Reflect.getField(mActivityThread, fieldName);
            for (Map.Entry<String, WeakReference<?>> entry : packageMap.entrySet()) {
                Object loadedApk = entry.getValue().get();
                if (loadedApk != null && Reflect.getField(loadedApk, "mApplication") == this) {
                    Reflect.setField(loadedApk, "mApplication", mRealApplication);
                }
            }
        }
    }
}
