// Copyright 2013 The Flutter 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 io.flutter.view;

import android.content.Context;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import io.flutter.embedding.engine.loader.FlutterLoader;

/**
 * A class to intialize the Flutter engine.
 */
public class FlutterMain {

    public static class Settings {
        private String logTag;

        @Nullable
        public String getLogTag() {
            return logTag;
        }

        /**
         * Set the tag associated with Flutter app log messages.
         * @param tag Log tag.
         */
        public void setLogTag(String tag) {
            logTag = tag;
        }
    }

    /**
     * Starts initialization of the native system.
     * @param applicationContext The Android application context.
     */
    public static void startInitialization(@NonNull Context applicationContext) {
        FlutterLoader.getInstance().startInitialization(applicationContext);
    }

    /**
     * Starts initialization of the native system.
     * <p>
     * This loads the Flutter engine's native library to enable subsequent JNI calls. This also
     * starts locating and unpacking Dart resources packaged in the app's APK.
     * <p>
     * Calling this method multiple times has no effect.
     *
     * @param applicationContext The Android application context.
     * @param settings Configuration settings.
     */
    public static void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
        FlutterLoader.Settings newSettings = new FlutterLoader.Settings();
        newSettings.setLogTag(settings.getLogTag());
        FlutterLoader.getInstance().startInitialization(applicationContext, newSettings);
    }

    /**
     * Blocks until initialization of the native system has completed.
     * <p>
     * Calling this method multiple times has no effect.
     *
     * @param applicationContext The Android application context.
     * @param args Flags sent to the Flutter runtime.
     */
    public static void ensureInitializationComplete(@NonNull Context applicationContext, @Nullable String[] args) {
        FlutterLoader.getInstance().ensureInitializationComplete(applicationContext, args);
    }

    /**
     * Same as {@link #ensureInitializationComplete(Context, String[])} but waiting on a background
     * thread, then invoking {@code callback} on the {@code callbackHandler}.
     */
    public static void ensureInitializationCompleteAsync(
        @NonNull Context applicationContext,
        @Nullable String[] args,
        @NonNull Handler callbackHandler,
        @NonNull Runnable callback
    ) {
        FlutterLoader.getInstance().ensureInitializationCompleteAsync(
            applicationContext, args, callbackHandler, callback);
    }

    @NonNull
    public static String findAppBundlePath() {
        return FlutterLoader.getInstance().findAppBundlePath();
    }

    @Deprecated
    @Nullable
    public static String findAppBundlePath(@NonNull Context applicationContext) {
        return FlutterLoader.getInstance().findAppBundlePath();
    }

    /**
     * Returns the file name for the given asset.
     * The returned file name can be used to access the asset in the APK
     * through the {@link android.content.res.AssetManager} API.
     *
     * @param asset the name of the asset. The name can be hierarchical
     * @return      the filename to be used with {@link android.content.res.AssetManager}
     */
    @NonNull
    public static String getLookupKeyForAsset(@NonNull String asset) {
        return FlutterLoader.getInstance().getLookupKeyForAsset(asset);
    }

    /**
     * Returns the file name for the given asset which originates from the
     * specified packageName. The returned file name can be used to access
     * the asset in the APK through the {@link android.content.res.AssetManager} API.
     *
     * @param asset       the name of the asset. The name can be hierarchical
     * @param packageName the name of the package from which the asset originates
     * @return            the file name to be used with {@link android.content.res.AssetManager}
     */
    @NonNull
    public static String getLookupKeyForAsset(@NonNull String asset, @NonNull String packageName) {
        return FlutterLoader.getInstance().getLookupKeyForAsset(asset, packageName);
    }
}

@@ -329,16 +329,69 @@
 ullable;
+%0Aimport android.support.annotation.VisibleForTesting;
 %0A%0Aimport
@@ -1095,32 +1095,104 @@
 ationContext) %7B%0A
+        if (isRunningInRobolectricTest) %7B%0A            return;%0A        %7D%0A
         FlutterL
@@ -1806,24 +1806,96 @@
 settings) %7B%0A
+        if (isRunningInRobolectricTest) %7B%0A            return;%0A        %7D%0A
         Flut
@@ -2501,24 +2501,96 @@
 g%5B%5D args) %7B%0A
+        if (isRunningInRobolectricTest) %7B%0A            return;%0A        %7D%0A
         Flut
@@ -3087,24 +3087,96 @@
 ack%0A    ) %7B%0A
+        if (isRunningInRobolectricTest) %7B%0A            return;%0A        %7D%0A
         Flut
@@ -4782,24 +4782,24 @@
 kageName) %7B%0A
-
         retu
@@ -4876,11 +4876,640 @@
 );%0A    %7D
+%0A%0A    private static boolean isRunningInRobolectricTest = false;%0A%0A    /*%0A     * Indicates whether we are currently running in a Robolectric Test.%0A     *%0A     * %3Cp%3E Flutter cannot be initialized inside a Robolectric environment since it cannot load%0A     * native libraries.%0A     *%0A     * @deprecated Use the new embedding (io.flutter.embedding) instead which provides better%0A     *     modularity for testing.%0A     */%0A    @Deprecated%0A    @VisibleForTesting%0A    public static void setIsRunningInRobolectricTest(boolean isRunningInRobolectricTest) %7B%0A        FlutterMain.isRunningInRobolectricTest = isRunningInRobolectricTest;%0A    %7D
 %0A%7D%0A

Add isRunningInRobolectricTest back (#13424)