chromium/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java

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

package org.chromium.chrome.browser.metrics;

import static androidx.test.espresso.matcher.ViewMatchers.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;

import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.ThreadUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.shared_preferences.SharedPreferencesManager;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisableIf;
import org.chromium.base.test.util.UserActionTester;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.app.bookmarks.BookmarkActivity;
import org.chromium.chrome.browser.app.download.home.DownloadActivity;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.history.HistoryActivity;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
import org.chromium.chrome.browser.settings.SettingsActivity;
import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.R;
import org.chromium.chrome.test.util.ActivityTestUtils;
import org.chromium.chrome.test.util.MenuUtils;
import org.chromium.components.browser_ui.settings.PlaceholderSettingsForTest;
import org.chromium.ui.test.util.UiDisableIf;

/** Tests the metrics recording for main intent behaviours. */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@SuppressLint({"ApplySharedPref", "CommitPrefEdits"})
public class MainIntentBehaviorMetricsIntegrationTest {
    private static final long HOURS_IN_MS = 60 * 60 * 1000L;

    @Rule
    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();

    @Rule
    public SettingsActivityTestRule<PlaceholderSettingsForTest> mSettingsActivityTestRule =
            new SettingsActivityTestRule<>(PlaceholderSettingsForTest.class);

    private UserActionTester mActionTester;

    @After
    public void tearDown() {
        if (mActionTester != null) mActionTester.tearDown();
    }

    @MediumTest
    @Test
    public void testBackgroundDuration_24hrs() {
        assertBackgroundDurationLogged(
                24 * HOURS_IN_MS, "MobileStartup.MainIntentReceived.After24Hours");
    }

    @MediumTest
    @Test
    public void testBackgroundDuration_12hrs() {
        assertBackgroundDurationLogged(
                12 * HOURS_IN_MS, "MobileStartup.MainIntentReceived.After12Hours");
    }

    @MediumTest
    @Test
    public void testBackgroundDuration_6hrs() {
        assertBackgroundDurationLogged(
                6 * HOURS_IN_MS, "MobileStartup.MainIntentReceived.After6Hours");
    }

    @MediumTest
    @Test
    public void testBackgroundDuration_1hr() {
        assertBackgroundDurationLogged(HOURS_IN_MS, "MobileStartup.MainIntentReceived.After1Hour");
    }

    @MediumTest
    @Test
    public void testBackgroundDuration_0hr() {
        assertBackgroundDurationLogged(0, null);
        for (String action : mActionTester.getActions()) {
            if (action.startsWith("MobileStartup.MainIntentReceived.After")) {
                Assert.fail("Unexpected background duration logged: " + action);
            }
        }
    }

    @MediumTest
    @Test
    public void testLaunch_Duration_MoreThan_1Day() {
        long timestamp = System.currentTimeMillis() - 25 * HOURS_IN_MS;
        SharedPreferencesManager prefs = ChromeSharedPreferences.getInstance();
        prefs.writeLongSync(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_TIMESTAMP, timestamp);
        prefs.writeIntSync(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_COUNT, 10);
        mActivityTestRule.startMainActivityFromLauncher();

        assertEquals(
                1,
                RecordHistogram.getHistogramValueCountForTesting(
                        "MobileStartup.DailyLaunchCount", 10));

        assertEquals(1, prefs.readInt(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_COUNT, 0));

        long newTimestamp =
                prefs.readLong(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_TIMESTAMP, 0);
        assertNotEquals(timestamp, newTimestamp);
        assertNotEquals(0, newTimestamp);
    }

    @MediumTest
    @Test
    public void testLaunch_Duration_LessThan_1Day() {
        long timestamp = System.currentTimeMillis() - 12 * HOURS_IN_MS;
        SharedPreferencesManager prefs = ChromeSharedPreferences.getInstance();
        prefs.writeLongSync(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_TIMESTAMP, timestamp);
        prefs.writeIntSync(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_COUNT, 1);
        mActivityTestRule.startMainActivityFromLauncher();

        assertEquals(
                0,
                RecordHistogram.getHistogramValueCountForTesting(
                        "MobileStartup.DailyLaunchCount", 1));

        assertEquals(2, prefs.readInt(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_COUNT, 0));

        assertEquals(
                timestamp,
                prefs.readLong(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_TIMESTAMP, 0));
    }

    @MediumTest
    @Test
    @DisableIf.Device(type = {UiDisableIf.TABLET}) // https://crbug.com/338974184
    public void testLaunch_From_InAppActivities() {
        try {
            MainIntentBehaviorMetrics.setTimeoutDurationMsForTesting(0);
            long timestamp = System.currentTimeMillis() - 12 * HOURS_IN_MS;
            SharedPreferencesManager prefs = ChromeSharedPreferences.getInstance();
            prefs.writeLongSync(
                    ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_TIMESTAMP, timestamp);

            mActivityTestRule.startMainActivityFromLauncher();

            SettingsActivity settingsActivity = mSettingsActivityTestRule.startSettingsActivity();
            settingsActivity.finish();
            ChromeActivityTestRule.waitForActivityNativeInitializationComplete(
                    ChromeActivityTestRule.waitFor(ChromeTabbedActivity.class));

            BookmarkActivity bookmarkActivity =
                    ActivityTestUtils.waitForActivity(
                            InstrumentationRegistry.getInstrumentation(),
                            BookmarkActivity.class,
                            new MenuUtils.MenuActivityTrigger(
                                    InstrumentationRegistry.getInstrumentation(),
                                    mActivityTestRule.getActivity(),
                                    R.id.all_bookmarks_menu_id));
            bookmarkActivity.finish();
            ChromeActivityTestRule.waitForActivityNativeInitializationComplete(
                    ChromeActivityTestRule.waitFor(ChromeTabbedActivity.class));

            DownloadActivity downloadActivity =
                    ActivityTestUtils.waitForActivity(
                            InstrumentationRegistry.getInstrumentation(),
                            DownloadActivity.class,
                            new MenuUtils.MenuActivityTrigger(
                                    InstrumentationRegistry.getInstrumentation(),
                                    mActivityTestRule.getActivity(),
                                    R.id.downloads_menu_id));
            downloadActivity.finish();
            ChromeActivityTestRule.waitForActivityNativeInitializationComplete(
                    ChromeActivityTestRule.waitFor(ChromeTabbedActivity.class));

            HistoryActivity historyActivity =
                    ActivityTestUtils.waitForActivity(
                            InstrumentationRegistry.getInstrumentation(),
                            HistoryActivity.class,
                            new MenuUtils.MenuActivityTrigger(
                                    InstrumentationRegistry.getInstrumentation(),
                                    mActivityTestRule.getActivity(),
                                    R.id.open_history_menu_id));
            historyActivity.finish();

            assertEquals(
                    1, prefs.readInt(ChromePreferenceKeys.METRICS_MAIN_INTENT_LAUNCH_COUNT, 0));
        } finally {
            MainIntentBehaviorMetrics.setTimeoutDurationMsForTesting(
                    MainIntentBehaviorMetrics.TIMEOUT_DURATION_MS);
        }
    }

    private void assertBackgroundDurationLogged(long duration, String expectedMetric) {
        startActivity(false);
        mActionTester = new UserActionTester();
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mActivityTestRule
                            .getActivity()
                            .getInactivityTrackerForTesting()
                            .setLastBackgroundedTimeInPrefs(System.currentTimeMillis() - duration);
                });

        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mActivityTestRule.getActivity().onNewIntent(intent);
                });

        assertThat(
                mActionTester.toString(),
                mActionTester.getActions(),
                Matchers.hasItem("MobileStartup.MainIntentReceived"));
        if (expectedMetric != null) {
            assertThat(
                    mActionTester.toString(),
                    mActionTester.getActions(),
                    Matchers.hasItem(expectedMetric));
        }
    }

    private void startActivityWithAboutBlank(boolean addLauncherCategory) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setData(Uri.parse("about:blank"));
        if (addLauncherCategory) intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setComponent(
                new ComponentName(
                        ApplicationProvider.getApplicationContext(), ChromeTabbedActivity.class));

        mActivityTestRule.startActivityCompletely(intent);
        mActivityTestRule.waitForActivityNativeInitializationComplete();
    }

    private void startActivity(boolean addLauncherCategory) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (addLauncherCategory) intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setComponent(
                new ComponentName(
                        ApplicationProvider.getApplicationContext(), ChromeTabbedActivity.class));

        mActivityTestRule.startActivityCompletely(intent);
        mActivityTestRule.waitForActivityNativeInitializationComplete();
    }
}