/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.wm;

import static android.perftests.utils.ManualBenchmarkState.STATS_REPORT_COEFFICIENT_VAR;
import static android.perftests.utils.ManualBenchmarkState.STATS_REPORT_ITERATION;
import static android.perftests.utils.ManualBenchmarkState.STATS_REPORT_MEAN;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static org.hamcrest.core.AnyOf.anyOf;
import static org.hamcrest.core.Is.is;

import android.app.Activity;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.SystemClock;
import android.perftests.utils.ManualBenchmarkState;
import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest;
import android.perftests.utils.PerfManualStatusReporter;
import android.perftests.utils.StubActivity;
import android.util.Pair;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
import android.view.WindowManager;

import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.lifecycle.ActivityLifecycleCallback;
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
import androidx.test.runner.lifecycle.Stage;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@RunWith(Parameterized.class)
@LargeTest
public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase {
    private static Intent sRecentsIntent;

    @Rule
    public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter();

    @Rule
    public final ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule<>(
            StubActivity.class, false /* initialTouchMode */, false /* launchActivity */);

    private long mMeasuredTimeNs;
    private LifecycleListener mLifecycleListener;

    @Parameterized.Parameter(0)
    public int intervalBetweenOperations;

    @Parameterized.Parameters(name = "interval{0}ms")
    public static Collection<Object[]> getParameters() {
        return Arrays.asList(new Object[][] {
                { 0 },
                { 100 },
                { 300 },
        });
    }

    @BeforeClass
    public static void setUpClass() {
        // Get the permission to invoke startRecentsActivity.
        sUiAutomation.adoptShellPermissionIdentity();

        final Context context = getInstrumentation().getContext();
        final PackageManager pm = context.getPackageManager();
        final ComponentName defaultHome = pm.getHomeActivities(new ArrayList<>());

        try {
            final ComponentName recentsComponent =
                    ComponentName.unflattenFromString(context.getResources().getString(
                            com.android.internal.R.string.config_recentsComponentName));
            final int enabledState = pm.getComponentEnabledSetting(recentsComponent);
            Assume.assumeThat(enabledState, anyOf(
                    is(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
                    is(PackageManager.COMPONENT_ENABLED_STATE_ENABLED)));

            final boolean homeIsRecents =
                    recentsComponent.getPackageName().equals(defaultHome.getPackageName());
            sRecentsIntent =
                    new Intent().setComponent(homeIsRecents ? defaultHome : recentsComponent);
        } catch (Exception e) {
            Assume.assumeNoException(e);
        }
    }

    @AfterClass
    public static void tearDownClass() {
        sUiAutomation.dropShellPermissionIdentity();
    }

    @Before
    @Override
    public void setUp() {
        super.setUp();
        final Activity testActivity = mActivityRule.launchActivity(null /* intent */);
        try {
            mActivityRule.runOnUiThread(() -> testActivity.getWindow()
                    .addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON));
        } catch (Throwable ignored) { }
        mLifecycleListener = new LifecycleListener(testActivity);
        ActivityLifecycleMonitorRegistry.getInstance().addLifecycleCallback(mLifecycleListener);
    }

    @After
    public void tearDown() {
        ActivityLifecycleMonitorRegistry.getInstance().removeLifecycleCallback(mLifecycleListener);
    }

    /** Simulate the timing of touch. */
    private void makeInterval() {
        SystemClock.sleep(intervalBetweenOperations);
    }

    /**
     * <pre>
     * Steps:
     * (1) Start recents activity (only make it visible).
     * (2) Finish animation, take turns to execute (a), (b).
     *     (a) Move recents activity to top.
     * ({@link com.android.server.wm.RecentsAnimationController#REORDER_MOVE_TO_TOP})
     *         Move test app to top by startActivityFromRecents.
     *     (b) Cancel (it is similar to swipe a little distance and give up to enter recents).
     * ({@link com.android.server.wm.RecentsAnimationController#REORDER_MOVE_TO_ORIGINAL_POSITION})
     * (3) Loop (1).
     * </pre>
     */
    @Test
    @ManualBenchmarkTest(
            warmupDurationNs = TIME_1_S_IN_NS,
            targetTestDurationNs = TIME_5_S_IN_NS,
            statsReportFlags =
                    STATS_REPORT_ITERATION | STATS_REPORT_MEAN | STATS_REPORT_COEFFICIENT_VAR)
    public void testRecentsAnimation() throws Throwable {
        final ManualBenchmarkState state = mPerfStatusReporter.getBenchmarkState();
        final IActivityTaskManager atm = ActivityTaskManager.getService();

        final ArrayList<Pair<String, Boolean>> finishCases = new ArrayList<>();
        // Real launch the recents activity.
        finishCases.add(new Pair<>("finishMoveToTop", true));
        // Return to the original top.
        finishCases.add(new Pair<>("finishCancel", false));

        // Ensure startRecentsActivity won't be called before finishing the animation.
        final Semaphore recentsSemaphore = new Semaphore(1);

        final int testActivityTaskId = mActivityRule.getActivity().getTaskId();
        final IRecentsAnimationRunner.Stub anim = new IRecentsAnimationRunner.Stub() {
            int mIteration;

            @Override
            public void onAnimationStart(IRecentsAnimationController controller,
                    RemoteAnimationTarget[] apps, Rect homeContentInsets,
                    Rect minimizedHomeBounds) throws RemoteException {
                final Pair<String, Boolean> finishCase = finishCases.get(mIteration++ % 2);
                final boolean moveRecentsToTop = finishCase.second;
                makeInterval();

                long startTime = SystemClock.elapsedRealtimeNanos();
                controller.finish(moveRecentsToTop, false /* sendUserLeaveHint */);
                final long elapsedTimeNsOfFinish = SystemClock.elapsedRealtimeNanos() - startTime;
                mMeasuredTimeNs += elapsedTimeNsOfFinish;
                state.addExtraResult(finishCase.first, elapsedTimeNsOfFinish);

                if (moveRecentsToTop) {
                    mLifecycleListener.waitForIdleSync(Stage.STOPPED);

                    startTime = SystemClock.elapsedRealtimeNanos();
                    atm.startActivityFromRecents(testActivityTaskId, null /* options */);
                    final long elapsedTimeNs = SystemClock.elapsedRealtimeNanos() - startTime;
                    mMeasuredTimeNs += elapsedTimeNs;
                    state.addExtraResult("startFromRecents", elapsedTimeNs);

                    mLifecycleListener.waitForIdleSync(Stage.RESUMED);
                }

                makeInterval();
                recentsSemaphore.release();
            }

            @Override
            public void onAnimationCanceled(boolean deferredWithScreenshot) throws RemoteException {
                Assume.assumeNoException(
                        new AssertionError("onAnimationCanceled should not be called"));
            }
        };

        while (state.keepRunning(mMeasuredTimeNs)) {
            Assume.assumeTrue(recentsSemaphore.tryAcquire(TIME_5_S_IN_NS, TimeUnit.NANOSECONDS));

            final long startTime = SystemClock.elapsedRealtimeNanos();
            atm.startRecentsActivity(sRecentsIntent, null /* unused */, anim);
            final long elapsedTimeNsOfStart = SystemClock.elapsedRealtimeNanos() - startTime;
            mMeasuredTimeNs += elapsedTimeNsOfStart;
            state.addExtraResult("start", elapsedTimeNsOfStart);
        }

        // Ensure the last round of animation callback is done.
        recentsSemaphore.tryAcquire(TIME_5_S_IN_NS, TimeUnit.NANOSECONDS);
        recentsSemaphore.release();
    }

    private static class LifecycleListener implements ActivityLifecycleCallback {
        private final Activity mTargetActivity;
        private Stage mWaitingStage;
        private Stage mReceivedStage;

        LifecycleListener(Activity activity) {
            mTargetActivity = activity;
        }

        void waitForIdleSync(Stage state) {
            synchronized (this) {
                if (state != mReceivedStage) {
                    mWaitingStage = state;
                    try {
                        wait(TimeUnit.NANOSECONDS.toMillis(TIME_5_S_IN_NS));
                    } catch (InterruptedException impossible) { }
                }
                mWaitingStage = mReceivedStage = null;
            }
            getInstrumentation().waitForIdleSync();
        }

        @Override
        public void onActivityLifecycleChanged(Activity activity, Stage stage) {
            if (mTargetActivity != activity) {
                return;
            }

            synchronized (this) {
                mReceivedStage = stage;
                if (mWaitingStage == mReceivedStage) {
                    notifyAll();
                }
            }
        }
    }
}
