summaryrefslogtreecommitdiff
path: root/tools/cts-media-preparer-app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java
blob: 7f80e5601e89862b198af51856e5dfa61fe72865 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * Copyright (C) 2016 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.mediastress.cts.preconditions.app;

import android.app.Instrumentation;
import android.media.MediaFormat;
import android.os.Bundle;

import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.DynamicConfigDeviceSide;
import com.android.compatibility.common.util.MediaUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Test class that uses device-side media APIs to determine up to which resolution MediaPreparer
 * should copy media files for CtsMediaStressTestCases.
 */
@RunWith(JUnit4.class)
public class MediaPreparerAppTest {

    /** The module name used to retrieve Dynamic Configuration data */
    private static final String MODULE_NAME = "CtsMediaStressTestCases";

    /** The default (minimum) resolution of media file to copy to the device */
    private static final int DEFAULT_MAX_WIDTH = 480;
    private static final int DEFAULT_MAX_HEIGHT = 360;

    /** Instrumentation status code used to write resolution to metrics */
    private static final int INST_STATUS_IN_PROGRESS = 2;

    /** Helper class for generating and retrieving width-height pairs */
    private static final class Resolution {
        // regex that matches a resolution string
        private static final String PATTERN = "(\\d+)x(\\d+)";
        // group indices for accessing resolution witdh/height from a Matcher created from PATTERN
        private static final int WIDTH_INDEX = 1;
        private static final int HEIGHT_INDEX = 2;

        private final int width;
        private final int height;

        private Resolution(int width, int height) {
            this.width = width;
            this.height = height;
        }

        private Resolution(String resolution) {
            Pattern pattern = Pattern.compile(PATTERN);
            Matcher matcher = pattern.matcher(resolution);
            matcher.find();
            this.width = Integer.parseInt(matcher.group(WIDTH_INDEX));
            this.height = Integer.parseInt(matcher.group(HEIGHT_INDEX));
        }

        @Override
        public String toString() {
            return String.format("%dx%d", width, height);
        }
    }

    @Test
    public void testGetResolutions() throws Exception {
        String moduleName = InstrumentationRegistry.getArguments().getString("module-name");
        if (moduleName == null) {
            moduleName = MODULE_NAME;
        }
        Resolution maxRes = new Resolution(DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT);
        DynamicConfigDeviceSide config = new DynamicConfigDeviceSide(moduleName);
        for (String key : config.keySet()) {
            int width = 0;
            int height = 0;
            for (MediaFormat format : stringsToFormats(config.getValues(key))) {
                try {
                    width = Math.max(width, format.getInteger(MediaFormat.KEY_WIDTH));
                    height = Math.max(height, format.getInteger(MediaFormat.KEY_HEIGHT));
                } catch (NullPointerException | ClassCastException e) {
                    // audio format, or invalid format created by unrelated dynamic config entry
                    // simply continue in this case
                }
            }
            Resolution fileResolution = new Resolution(width, height);
            // if the file is of greater resolution than maxRes, check for support
            if (fileResolution.width > maxRes.width) {
                boolean supported = true;
                for (MediaFormat format : stringsToFormats(config.getValues(key))) {
                    supported &= MediaUtils.checkDecoderForFormat(format);
                }
                if (supported) {
                    // update if all MediaFormats for file are supported by device
                    maxRes = fileResolution;
                }
            }
        }
        // write resolution string to metrics
        Instrumentation inst = InstrumentationRegistry.getInstrumentation();
        Bundle maxResBundle = new Bundle();
        maxResBundle.putString("resolution", maxRes.toString());
        inst.sendStatus(INST_STATUS_IN_PROGRESS, maxResBundle);
    }

    /**
     * Converts string representations of MediaFormats into actual MediaFormats
     * @param formatStrings a list of string representations of MediaFormats. Each input string
     * may represent one or more MediaFormats
     * @return a list of MediaFormats
     */
    private List<MediaFormat> stringsToFormats(List<String> formatStrings) {
        List<MediaFormat> formats = new ArrayList<MediaFormat>();
        for (String formatString : formatStrings) {
            for (String trackFormatString : formatString.split(";")) {
                formats.add(parseTrackFormat(trackFormatString));
            }
        }
        return formats;
    }

    /**
     * Converts a single media track format string into a MediaFormat object
     * @param trackFormatString a string representation of the format of one media track
     * @return a MediaFormat
     */
    private static MediaFormat parseTrackFormat(String trackFormatString) {
        MediaFormat format = new MediaFormat();
        format.setString(MediaFormat.KEY_MIME, "");
        for (String entry : trackFormatString.split(",")) {
            String[] kv = entry.split("=");
            if (kv.length < 2) {
                continue;
            }
            String k = kv[0];
            String v = kv[1];
            try {
                format.setInteger(k, Integer.parseInt(v));
            } catch(NumberFormatException e) {
                format.setString(k, v);
            }
        }
        return format;
    }
}