// Copyright 2023 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 android.app.ActivityManager;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.os.Build;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivityManager;
import org.robolectric.shadows.ShadowUsageStatsManager;

import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.HistogramWatcher;

/**
 * Unit tests for {@link UmaUtils}.
 */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class UmaUtilsTest {
    private static final String HISTOGRAM_IS_BACKGROUND_RESTRICTED =
            "Android.BackgroundRestrictions.IsBackgroundRestricted";
    private static final String HISTOGRAM_STANDBY_BUCKET =
            "Android.BackgroundRestrictions.StandbyBucket";
    private static final String HISTOGRAM_STANDBY_BUCKET_WITH_USER_RESTRICTION =
            "Android.BackgroundRestrictions.StandbyBucket.WithUserRestriction";
    private static final String HISTOGRAM_MINIDUMP_UPLOADING_TIME =
            "Stability.Android.MinidumpUploadingTime";

    private ShadowActivityManager mShadowActivityManager;
    private ShadowUsageStatsManager mShadowUsageStatsManager;

    @Before
    public void setUp() {
        mShadowActivityManager = Shadows.shadowOf(
                (ActivityManager) RuntimeEnvironment.getApplication().getSystemService(
                        Context.ACTIVITY_SERVICE));
        mShadowUsageStatsManager = Shadows.shadowOf(
                (UsageStatsManager) RuntimeEnvironment.getApplication().getSystemService(
                        Context.USAGE_STATS_SERVICE));
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.O_MR1)
    public void testRecordBackgroundRestrictions_noRestrictionsUnderPie() {
        // Arrange
        var histogramWatcher =
                HistogramWatcher.newBuilder()
                        .expectNoRecords(HISTOGRAM_IS_BACKGROUND_RESTRICTED)
                        .expectNoRecords(HISTOGRAM_STANDBY_BUCKET)
                        .expectNoRecords(HISTOGRAM_STANDBY_BUCKET_WITH_USER_RESTRICTION)
                        .build();

        // Act
        UmaUtils.recordBackgroundRestrictions();

        // Assert
        histogramWatcher.assertExpected();
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_notRestricted_standbyBucketActive() {
        int androidStandbyBucketStatus = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
        int expectedUmaStandbyBucketStatus = 0; // StandbyBucketStatus.ACTIVE is 0 in enums.xml

        doTestRecordBackgroundRestrictions_notRestricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_notRestricted_standbyBucketWorkingSet() {
        int androidStandbyBucketStatus = UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
        int expectedUmaStandbyBucketStatus = 1; // StandbyBucketStatus.WORKING_SET is 1 in enums.xml

        doTestRecordBackgroundRestrictions_notRestricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_notRestricted_standbyBucketFrequent() {
        int androidStandbyBucketStatus = UsageStatsManager.STANDBY_BUCKET_FREQUENT;
        int expectedUmaStandbyBucketStatus = 2; // StandbyBucketStatus.FREQUENT is 2 in enums.xml

        doTestRecordBackgroundRestrictions_notRestricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_restricted_standbyBucketRare() {
        int androidStandbyBucketStatus = UsageStatsManager.STANDBY_BUCKET_RARE;
        int expectedUmaStandbyBucketStatus = 3; // StandbyBucketStatus.RARE is 3 in enums.xml

        doTestRecordBackgroundRestrictions_restricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_notRestricted_standbyBucketRare() {
        int androidStandbyBucketStatus = UsageStatsManager.STANDBY_BUCKET_RARE;
        int expectedUmaStandbyBucketStatus = 3; // StandbyBucketStatus.RARE is 3 in enums.xml

        doTestRecordBackgroundRestrictions_notRestricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_restricted_standbyBucketRestricted() {
        int androidStandbyBucketStatus = UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
        int expectedUmaStandbyBucketStatus = 4; // StandbyBucketStatus.RESTRICTED is 4 in enums.xml

        doTestRecordBackgroundRestrictions_restricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_notRestricted_standbyBucketExempted() {
        int androidStandbyBucketStatus = 5; // UsageStatsManager.STANDBY_BUCKET_EXEMPTED
        int expectedStandbyBucketStatus = 6; // StandbyBucketStatus.EXEMPTED is 6 in enums.xml

        doTestRecordBackgroundRestrictions_notRestricted(
                androidStandbyBucketStatus, expectedStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_restricted_standbyBucketNever() {
        int androidStandbyBucketStatus = 50; // UsageStatsManager.STANDBY_BUCKET_NEVER
        int expectedUmaStandbyBucketStatus = 7; // StandbyBucketStatus.NEVER is 7 in enums.xml

        doTestRecordBackgroundRestrictions_restricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    @Test
    @Config(sdk = Build.VERSION_CODES.P)
    public void testRecordBackgroundRestrictions_restricted_standbyBucketOther() {
        int androidStandbyBucketStatus = 42; // UsageStatsManager.STANDBY_BUCKET_OTHER
        int expectedUmaStandbyBucketStatus = 8; // StandbyBucketStatus.OTHER is 8 in enums.xml

        doTestRecordBackgroundRestrictions_restricted(
                androidStandbyBucketStatus, expectedUmaStandbyBucketStatus);
    }

    private void doTestRecordBackgroundRestrictions_notRestricted(
            int androidStandbyBucketStatus, int expectedUmaStandbyBucketStatus) {
        // Arrange
        mShadowActivityManager.setBackgroundRestricted(false);
        mShadowUsageStatsManager.setCurrentAppStandbyBucket(androidStandbyBucketStatus);

        var histogramWatcher =
                HistogramWatcher.newBuilder()
                        .expectBooleanRecord(HISTOGRAM_IS_BACKGROUND_RESTRICTED, false)
                        .expectIntRecord(HISTOGRAM_STANDBY_BUCKET, expectedUmaStandbyBucketStatus)
                        .expectNoRecords(HISTOGRAM_STANDBY_BUCKET_WITH_USER_RESTRICTION)
                        .build();

        // Act
        UmaUtils.recordBackgroundRestrictions();

        // Assert
        histogramWatcher.assertExpected();
    }

    private void doTestRecordBackgroundRestrictions_restricted(
            int androidStandbyBucketStatus, int expectedUmaStandbyBucketStatus) {
        // Arrange
        mShadowActivityManager.setBackgroundRestricted(true);
        mShadowUsageStatsManager.setCurrentAppStandbyBucket(androidStandbyBucketStatus);

        var histogramWatcher =
                HistogramWatcher.newBuilder()
                        .expectBooleanRecord(HISTOGRAM_IS_BACKGROUND_RESTRICTED, true)
                        .expectIntRecord(HISTOGRAM_STANDBY_BUCKET, expectedUmaStandbyBucketStatus)
                        .expectIntRecord(HISTOGRAM_STANDBY_BUCKET_WITH_USER_RESTRICTION,
                                expectedUmaStandbyBucketStatus)
                        .build();

        // Act
        UmaUtils.recordBackgroundRestrictions();

        // Assert
        histogramWatcher.assertExpected();
    }
}
