/*
 * Copyright (C) 2021 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.mediapc.cts;

import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_SecurePlayback;
import static android.mediapc.cts.common.Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB;
import static android.mediapc.cts.common.Utils.MIN_MEMORY_PERF_CLASS_T_MB;
import static android.util.DisplayMetrics.DENSITY_400;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertTrue;

import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaDrm;
import android.media.MediaFormat;
import android.media.UnsupportedSchemeException;
import android.mediapc.cts.common.PerformanceClassEvaluator;
import android.mediapc.cts.common.Utils;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;

import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;

import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;

import java.io.IOException;
import java.util.ArrayList;
import java.util.UUID;

/**
 * Tests the basic aspects of the media performance class.
 */
public class PerformanceClassTest {
    private static final String TAG = "PerformanceClassTest";
    private static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL);
    static ArrayList<String> mMimeSecureSupport = new ArrayList<>();

    @Rule
    public final TestName mTestName = new TestName();

    static {
        mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_AVC);
        mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
        mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_VP9);
        mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_AV1);
    }


    private boolean isHandheld() {
        // handheld nature is not exposed to package manager, for now
        // we check for touchscreen and NOT watch and NOT tv
        PackageManager pm =
            InstrumentationRegistry.getInstrumentation().getContext().getPackageManager();
        return pm.hasSystemFeature(pm.FEATURE_TOUCHSCREEN)
                && !pm.hasSystemFeature(pm.FEATURE_WATCH)
                && !pm.hasSystemFeature(pm.FEATURE_TELEVISION)
                && !pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE);
    }

    @SmallTest
    @Test
    // TODO(b/218771970) Add @CddTest annotation
    public void testSecureHwDecodeSupport() throws IOException {
        ArrayList<String> noSecureHwDecoderForMimes = new ArrayList<>();
        for (String mime : mMimeSecureSupport) {
            boolean isSecureHwDecoderFoundForMime = false;
            boolean isHwDecoderFoundForMime = false;
            MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
            MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
            for (MediaCodecInfo info : codecInfos) {
                if (info.isEncoder() || !info.isHardwareAccelerated() || info.isAlias()) continue;
                try {
                    MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
                    if (caps != null) {
                        isHwDecoderFoundForMime = true;
                        if (caps.isFeatureSupported(FEATURE_SecurePlayback))
                            isSecureHwDecoderFoundForMime = true;
                    }
                } catch (Exception ignored) {
                }
            }
            if (isHwDecoderFoundForMime && !isSecureHwDecoderFoundForMime)
                noSecureHwDecoderForMimes.add(mime);
        }
        if (Utils.isTPerfClass()) {
            assertTrue(
                    "For MPC >= Android T, if HW decoder is present for a mime, secure HW decoder" +
                            " must be present for the mime. HW decoder present but secure HW " +
                            "decoder not available for mimes: " + noSecureHwDecoderForMimes,
                    noSecureHwDecoderForMimes.isEmpty());
        } else {
            DeviceReportLog log =
                    new DeviceReportLog("MediaPerformanceClassLogs", "SecureHwDecodeSupport");
            log.addValue("SecureHwDecodeSupportForMimesWithHwDecoders",
                    noSecureHwDecoderForMimes.isEmpty(), ResultType.NEUTRAL, ResultUnit.NONE);
            // TODO(b/218771970) Log CDD sections
            log.setSummary("MPC 13: Widevine/Secure codec requirements", 0, ResultType.NEUTRAL,
                    ResultUnit.NONE);
            log.submit(InstrumentationRegistry.getInstrumentation());
        }
    }

    @SmallTest
    @Test
    // TODO(b/218771970) Add @CddTest annotation
    public void testWidevineSupport() throws UnsupportedSchemeException {
        boolean isWidevineSupported = MediaDrm.isCryptoSchemeSupported(WIDEVINE_UUID);
        boolean isL1Supported = false;
        boolean isL1Tier3Supported = false;
        boolean isOemCrypto17Plus = false;
        boolean isWidevineCdm17Plus = false;
        if (isWidevineSupported) {
            MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID);
            isL1Supported = mediaDrm.getPropertyString("securityLevel").equals("L1");
            int tier = Integer.parseInt(mediaDrm.getPropertyString("resourceRatingTier"));
            isL1Tier3Supported = tier >= 3;

            String oemCryptoVersionProperty = mediaDrm.getPropertyString("oemCryptoApiVersion");
            int oemCryptoVersion = Integer.parseInt(oemCryptoVersionProperty);
            isOemCrypto17Plus = oemCryptoVersion >= 17;

            String cdmVersionProperty = mediaDrm.getPropertyString(MediaDrm.PROPERTY_VERSION);
            int cdmMajorVersion = Integer.parseInt(cdmVersionProperty.split("\\.", 2)[0]);
            isWidevineCdm17Plus = cdmMajorVersion >= 17;
        }

        if (Utils.isTPerfClass()) {
            assertTrue("Widevine support required for MPC >= Android T", isWidevineSupported);
            assertTrue("Widevine L1 support required for MPC >= Android T", isL1Supported);
            assertTrue("Widevine L1 Resource Rating Tier 3 support required for MPC >= Android T",
                    isL1Tier3Supported);
            assertTrue("OEMCrypto min version 17.x required for MPC >= Android T",
                    isOemCrypto17Plus);
            assertTrue("Widevine CDM min version 17.x required for MPC >= Android T",
                    isWidevineCdm17Plus);
        } else {
            DeviceReportLog log =
                    new DeviceReportLog("MediaPerformanceClassLogs", "WidevineSupport");
            log.addValue("Widevine Support", isWidevineSupported, ResultType.NEUTRAL,
                    ResultUnit.NONE);
            log.addValue("Widevine L1 Support", isL1Supported, ResultType.NEUTRAL, ResultUnit.NONE);
            log.addValue("Widevine L1 Resource Rating Tier 3 Support", isL1Tier3Supported,
                    ResultType.NEUTRAL, ResultUnit.NONE);
            log.addValue("OEMCrypto min version 17.x Support", isOemCrypto17Plus,
                    ResultType.NEUTRAL, ResultUnit.NONE);
            log.addValue("Widevine CDM min version 17.x Support", isWidevineCdm17Plus,
                    ResultType.NEUTRAL, ResultUnit.NONE);
            // TODO(b/218771970) Log CDD sections
            log.setSummary("MPC 13: Widevine/Secure codec requirements", 0, ResultType.NEUTRAL,
                    ResultUnit.NONE);
            log.submit(InstrumentationRegistry.getInstrumentation());
        }
    }

    @SmallTest
    @Test
    public void testMediaPerformanceClassScope() throws Exception {
        // if device is not of a performance class, we are done.
        Assume.assumeTrue("not a device of a valid media performance class", Utils.isPerfClass());

        if (Utils.isPerfClass()) {
            assertTrue("performance class is only defined for Handheld devices", isHandheld());
        }
    }

    @Test
    @CddTest(requirements={
        "2.2.7.3/7.1.1.1/H-1-1",
        "2.2.7.3/7.1.1.1/H-2-1",
        "2.2.7.3/7.1.1.3/H-1-1",
        "2.2.7.3/7.1.1.3/H-2-1",
        "2.2.7.3/7.6.1/H-1-1",
        "2.2.7.3/7.6.1/H-2-1",
        "2.2.7.3/7.6.1/H-3-1"})
    public void testMinimumMemory() {
        Context context = InstrumentationRegistry.getInstrumentation().getContext();

        // Verify minimum screen density and resolution
        assertMinDpiAndPixels(context, DENSITY_400, 1920, 1080);
        // Verify minimum memory
        assertMinMemoryMb(context);
    }

    /** Asserts that the given values conform to the specs in CDD */
    private void assertMinDpiAndPixels(Context context, int minDpi, int minLong, int minShort) {
        // Verify display DPI. We only seem to be able to get the primary display.
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager windowManager =
            (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        windowManager.getDefaultDisplay().getMetrics(metrics);
        int density = metrics.densityDpi;
        int longPix = Math.max(metrics.widthPixels, metrics.heightPixels);
        int shortPix = Math.min(metrics.widthPixels, metrics.heightPixels);

        Log.i(TAG, String.format("minDpi=%d minSize=%dx%dpix", minDpi, minLong, minShort));
        Log.i(TAG, String.format("dpi=%d size=%dx%dpix", density, longPix, shortPix));

        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
        PerformanceClassEvaluator.ResolutionRequirement r7_1_1_1__h_1_1 = pce.addR7_1_1_1__H_1_1();
        PerformanceClassEvaluator.DensityRequirement r7_1_1_3__h_1_1 = pce.addR7_1_1_3__H_1_1();
        PerformanceClassEvaluator.ResolutionRequirement r7_1_1_1__h_2_1 = pce.addR7_1_1_1__H_2_1();
        PerformanceClassEvaluator.DensityRequirement r7_1_1_3__h_2_1 = pce.addR7_1_1_3__H_2_1();

        r7_1_1_1__h_1_1.setLongResolution(longPix);
        r7_1_1_1__h_2_1.setLongResolution(longPix);
        r7_1_1_1__h_1_1.setShortResolution(shortPix);
        r7_1_1_1__h_2_1.setShortResolution(shortPix);

        r7_1_1_3__h_1_1.setDisplayDensity(density);
        r7_1_1_3__h_2_1.setDisplayDensity(density);

        pce.submitAndCheck();
    }

    /** Asserts that the given values conform to the specs in CDD 7.6.1 */
    private void assertMinMemoryMb(Context context) {
        ActivityManager activityManager = context.getSystemService(ActivityManager.class);
        long totalMemoryMb = getTotalMemory(activityManager) / 1024 / 1024;

        Log.i(TAG, String.format("Total device memory = %,d MB", totalMemoryMb));

        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
        PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_1_1 = pce.addR7_6_1__H_1_1();
        PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_2_1 = pce.addR7_6_1__H_2_1();

        r7_6_1_h_1_1.setPhysicalMemory(totalMemoryMb);
        r7_6_1_h_2_1.setPhysicalMemory(totalMemoryMb);

        pce.submitAndCheck();
    }

    /**
     * @return the total memory accessible by the kernel as defined by
     * {@code ActivityManager.MemoryInfo}.
     */
    private long getTotalMemory(ActivityManager activityManager) {
        ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
        activityManager.getMemoryInfo(memoryInfo);
        return memoryInfo.totalMem;
    }
}
