/*
 * 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.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_ALL;
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.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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;

/**
 * Tests the basic aspects of the media performance class.
 */
public class PerformanceClassTest {
    private static final String TAG = "PerformanceClassTest";
    public static final String[] VIDEO_CONTAINER_MEDIA_TYPES =
        {"video/mp4", "video/webm", "video/3gpp", "video/3gpp2", "video/avi", "video/x-ms-wmv",
            "video/x-ms-asf"};
    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
    @CddTest(requirements = {"2.2.7.1/5.1/H-1-11"})
    public void testSecureHwDecodeSupport() {
        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);
        }

        boolean secureDecodeSupportIfHwDecoderPresent = noSecureHwDecoderForMimes.isEmpty();

        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
        PerformanceClassEvaluator.SecureCodecRequirement r5_1__H_1_11 = pce.addR5_1__H_1_11();
        r5_1__H_1_11.setSecureReqSatisfied(secureDecodeSupportIfHwDecoderPresent);

        pce.submitAndCheck();
    }

    @SmallTest
    @Test
    @CddTest(requirements = {"2.2.7.1/5.7/H-1-2"})
    public void testMediaDrmSecurityLevelHwSecureAll() throws UnsupportedSchemeException {
        List<UUID> drmList = MediaDrm.getSupportedCryptoSchemes();
        List<UUID> supportedHwSecureAllSchemes = new ArrayList<>();

        for (UUID cryptoSchemeUUID : drmList) {
            boolean cryptoSchemeSupportedForAtleastOneMediaType = false;
            for (String mediaType : VIDEO_CONTAINER_MEDIA_TYPES) {
                cryptoSchemeSupportedForAtleastOneMediaType |= MediaDrm
                    .isCryptoSchemeSupported(cryptoSchemeUUID, mediaType,
                        SECURITY_LEVEL_HW_SECURE_ALL);
            }
            if (cryptoSchemeSupportedForAtleastOneMediaType) {
                supportedHwSecureAllSchemes.add(cryptoSchemeUUID);
            }
        }

        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
        PerformanceClassEvaluator.SecureCodecRequirement r5_7__H_1_2 = pce.addR5_7__H_1_2();

        r5_7__H_1_2.setNumCryptoHwSecureAllDec(supportedHwSecureAllSchemes.size());

        pce.submitAndCheck();
    }

    @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",})
    public void testMinimumResolutionAndDensity() {
        Context context = InstrumentationRegistry.getInstrumentation().getContext();

        // 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("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();
    }

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

        // Verify minimum memory
        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;
    }
}
