blob: 8c91c5bc52d7600bc8e4e86ff68c9018aa57e04e [file] [log] [blame]
/*
* 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.media.metrics.cts;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.media.metrics.BundleSession;
import android.media.metrics.EditingSession;
import android.media.metrics.LogSessionId;
import android.media.metrics.MediaMetricsManager;
import android.media.metrics.NetworkEvent;
import android.media.metrics.PlaybackErrorEvent;
import android.media.metrics.PlaybackMetrics;
import android.media.metrics.PlaybackSession;
import android.media.metrics.PlaybackStateEvent;
import android.media.metrics.RecordingSession;
import android.media.metrics.TrackChangeEvent;
import android.media.metrics.TranscodingSession;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.provider.DeviceConfig;
import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.SystemUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@RunWith(AndroidJUnit4.class)
public class MediaMetricsAtomHostSideTests {
private static final String TAG = "MediaMetricsAtomHostSideTests";
private static final String MEDIA_METRICS_MODE = "media_metrics_mode";
private static final String PLAYER_METRICS_APP_ALLOWLIST = "player_metrics_app_allowlist";
private static final String PLAYER_METRICS_APP_BLOCKLIST = "player_metrics_app_blocklist";
private static final String PLAYER_METRICS_PER_APP_ATTRIBUTION_ALLOWLIST =
"player_metrics_per_app_attribution_allowlist";
private static final String PLAYER_METRICS_PER_APP_ATTRIBUTION_BLOCKLIST =
"player_metrics_per_app_attribution_blocklist";
private static final String MEDIA_METRICS_MODE_ON = "1";
private static final String MEDIA_METRICS_MODE_BLOCKLIST = "2";
private static final String MEDIA_METRICS_MODE_ALLOWLIST = "3";
private static final String TEST_PKG = "android.media.metrics.cts";
private static final int DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS = 1000;
static {
System.loadLibrary("CtsMediaMetricsHostTestAppJni");
}
private static void resetProperties() throws InterruptedException {
// ensure the event/metric is sent.
Thread.sleep(1000);
// see DeviceConfig#resetToDefaults(int, String).
SystemUtil.runWithShellPermissionIdentity(() -> {
DeviceConfig.setProperties(
new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA).build());
});
// ensure the property is set.
Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
}
private static void turnOnForTesting() throws InterruptedException {
SystemUtil.runWithShellPermissionIdentity(() -> {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_MEDIA,
MEDIA_METRICS_MODE,
MEDIA_METRICS_MODE_ON,
/*makeDefault=*/ false);
});
// ensure the property is set.
Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
}
@Test
public void testPlaybackStateEvent_default() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackStateEvent e =
new PlaybackStateEvent.Builder().build();
s.reportPlaybackStateEvent(e);
resetProperties();
}
@Test
public void testPlaybackStateEvent() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackStateEvent e =
new PlaybackStateEvent.Builder()
.setTimeSinceCreatedMillis(1763L)
.setState(PlaybackStateEvent.STATE_JOINING_FOREGROUND)
.setMetricsBundle(new Bundle())
.build();
s.reportPlaybackStateEvent(e);
resetProperties();
}
@Test
public void testPlaybackErrorEvent_default() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackErrorEvent e =
new PlaybackErrorEvent.Builder()
.setException(new Exception(""))
.build();
s.reportPlaybackErrorEvent(e);
resetProperties();
}
@Test
public void testPlaybackErrorEvent() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackErrorEvent e =
new PlaybackErrorEvent.Builder()
.setTimeSinceCreatedMillis(17630000L)
.setErrorCode(PlaybackErrorEvent.ERROR_RUNTIME)
.setSubErrorCode(378)
.setException(new Exception("test exception"))
.setMetricsBundle(new Bundle())
.build();
s.reportPlaybackErrorEvent(e);
resetProperties();
}
@Test
public void testTrackChangeEvent_default() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
TrackChangeEvent e =
new TrackChangeEvent.Builder(TrackChangeEvent.TRACK_TYPE_AUDIO).build();
s.reportTrackChangeEvent(e);
resetProperties();
}
@Test
public void testTrackChangeEvent_text() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
TrackChangeEvent e =
new TrackChangeEvent.Builder(TrackChangeEvent.TRACK_TYPE_TEXT)
.setTimeSinceCreatedMillis(37278L)
.setTrackState(TrackChangeEvent.TRACK_STATE_ON)
.setTrackChangeReason(TrackChangeEvent.TRACK_CHANGE_REASON_MANUAL)
.setContainerMimeType("text/foo")
.setSampleMimeType("text/plain")
.setCodecName("codec_1")
.setBitrate(1024)
.setLanguage("EN")
.setLanguageRegion("US")
.build();
s.reportTrackChangeEvent(e);
resetProperties();
}
@Test
public void testTrackChangeEvent_audio() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
TrackChangeEvent e =
new TrackChangeEvent.Builder(TrackChangeEvent.TRACK_TYPE_AUDIO)
.setTimeSinceCreatedMillis(37278L)
.setTrackState(TrackChangeEvent.TRACK_STATE_OFF)
.setTrackChangeReason(TrackChangeEvent.TRACK_CHANGE_REASON_INITIAL)
.setContainerMimeType("audio/foo")
.setSampleMimeType("audio/avc")
.setCodecName("codec_2")
.setBitrate(1025)
.setLanguage("EN")
.setLanguageRegion("US")
.setAudioSampleRate(89)
.setChannelCount(3)
.build();
s.reportTrackChangeEvent(e);
resetProperties();
}
@Test
public void testTrackChangeEvent_video() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
TrackChangeEvent e =
new TrackChangeEvent.Builder(TrackChangeEvent.TRACK_TYPE_VIDEO)
.setTimeSinceCreatedMillis(37278L)
.setTrackState(TrackChangeEvent.TRACK_STATE_OFF)
.setTrackChangeReason(TrackChangeEvent.TRACK_CHANGE_REASON_INITIAL)
.setContainerMimeType("video/foo")
.setSampleMimeType("video/mpeg")
.setCodecName("codec_3")
.setBitrate(1025)
.setLanguage("EN")
.setLanguageRegion("US")
.setHeight(1080)
.setWidth(1440)
.setVideoFrameRate(60)
.setMetricsBundle(new Bundle())
.build();
s.reportTrackChangeEvent(e);
resetProperties();
}
@Test
public void testNetworkEvent_default() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
NetworkEvent e =
new NetworkEvent.Builder().build();
s.reportNetworkEvent(e);
resetProperties();
}
@Test
public void testNetworkEvent() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
NetworkEvent e =
new NetworkEvent.Builder()
.setTimeSinceCreatedMillis(3032L)
.setNetworkType(NetworkEvent.NETWORK_TYPE_WIFI)
.setMetricsBundle(new Bundle())
.build();
s.reportNetworkEvent(e);
resetProperties();
}
@Test
public void testPlaybackMetrics_default() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackMetrics e =
new PlaybackMetrics.Builder().build();
s.reportPlaybackMetrics(e);
resetProperties();
}
@Test
public void testPlaybackMetrics() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackMetrics e =
new PlaybackMetrics.Builder()
.setMediaDurationMillis(233L)
.setStreamSource(PlaybackMetrics.STREAM_SOURCE_NETWORK)
.setStreamType(PlaybackMetrics.STREAM_TYPE_OTHER)
.setPlaybackType(PlaybackMetrics.PLAYBACK_TYPE_LIVE)
.setDrmType(PlaybackMetrics.DRM_TYPE_WIDEVINE_L1)
.setContentType(PlaybackMetrics.CONTENT_TYPE_MAIN)
.setPlayerName("ExoPlayer")
.setPlayerVersion("1.01x")
.setVideoFramesPlayed(1024)
.setVideoFramesDropped(32)
.setAudioUnderrunCount(22)
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
.setDrmSessionId(new byte[] {2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
s.reportPlaybackMetrics(e);
resetProperties();
}
@Test
public void testSessionId() throws Exception {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
try (PlaybackSession s = manager.createPlaybackSession()) {
LogSessionId idObj = s.getSessionId();
assertThat(idObj).isNotEqualTo(null);
assertThat(idObj.getStringId().length()).isGreaterThan(0);
}
}
@Test
public void testRecordingSession() throws Exception {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
try (RecordingSession s = manager.createRecordingSession()) {
assertThat(s).isNotEqualTo(null);
LogSessionId idObj = s.getSessionId();
assertThat(idObj).isNotEqualTo(null);
assertThat(idObj.getStringId().length()).isGreaterThan(0);
}
}
@Test
public void testEditingSession() throws Exception {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
try (EditingSession s = manager.createEditingSession()) {
assertThat(s).isNotEqualTo(null);
LogSessionId idObj = s.getSessionId();
assertThat(idObj).isNotEqualTo(null);
assertThat(idObj.getStringId().length()).isGreaterThan(0);
}
}
@Test
public void testTranscodingSession() throws Exception {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
try (TranscodingSession s = manager.createTranscodingSession()) {
assertThat(s).isNotEqualTo(null);
LogSessionId idObj = s.getSessionId();
assertThat(idObj).isNotEqualTo(null);
assertThat(idObj.getStringId().length()).isGreaterThan(0);
}
}
@Test
public void testBundleSession() throws Exception {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
try (BundleSession s = manager.createBundleSession()) {
assertThat(s).isNotEqualTo(null);
LogSessionId idObj = s.getSessionId();
assertThat(idObj).isNotEqualTo(null);
assertThat(idObj.getStringId().length()).isGreaterThan(0);
}
}
@Test
public void testBundleSessionPlaybackStateEvent() throws Exception {
turnOnForTesting();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
BundleSession s = manager.createBundleSession();
PersistableBundle b = new PersistableBundle();
b.putInt(BundleSession.KEY_STATSD_ATOM, 322);
// eventually want these keys from within the service side.
b.putString("playbackstateevent-sessionid", s.getSessionId().getStringId());
b.putInt("playbackstateevent-state", PlaybackStateEvent.STATE_JOINING_FOREGROUND);
b.putLong("playbackstateevent-lifetime", 1763L);
s.reportBundleMetrics(b);
resetProperties();
}
@Test
public void testAppBlocklist() throws Exception {
SystemUtil.runWithShellPermissionIdentity(() -> {
DeviceConfig.setProperties(
new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
.setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_BLOCKLIST)
.setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_BLOCKLIST, "")
.setString(PLAYER_METRICS_APP_BLOCKLIST, TEST_PKG)
.build());
});
Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackStateEvent e =
new PlaybackStateEvent.Builder()
.setTimeSinceCreatedMillis(1763L)
.setState(PlaybackStateEvent.STATE_JOINING_FOREGROUND)
.setMetricsBundle(new Bundle())
.build();
s.reportPlaybackStateEvent(e);
writeSessionIdToFile(s.getSessionId().getStringId());
resetProperties();
}
@Test
public void testAttributionBlocklist() throws Exception {
SystemUtil.runWithShellPermissionIdentity(() -> {
DeviceConfig.setProperties(
new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
.setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_BLOCKLIST)
.setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_BLOCKLIST, TEST_PKG)
.setString(PLAYER_METRICS_APP_BLOCKLIST, "")
.build());
});
Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackMetrics e =
new PlaybackMetrics.Builder()
.setMediaDurationMillis(233L)
.setStreamSource(PlaybackMetrics.STREAM_SOURCE_NETWORK)
.setStreamType(PlaybackMetrics.STREAM_TYPE_OTHER)
.setPlaybackType(PlaybackMetrics.PLAYBACK_TYPE_LIVE)
.setDrmType(PlaybackMetrics.DRM_TYPE_WIDEVINE_L1)
.setContentType(PlaybackMetrics.CONTENT_TYPE_MAIN)
.setPlayerName("ExoPlayer")
.setPlayerVersion("1.01x")
.setVideoFramesPlayed(1024)
.setVideoFramesDropped(32)
.setAudioUnderrunCount(22)
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
.setDrmSessionId(new byte[] {2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
s.reportPlaybackMetrics(e);
writeSessionIdToFile(s.getSessionId().getStringId());
resetProperties();
}
@Test
public void testAppAllowlist() throws Exception {
SystemUtil.runWithShellPermissionIdentity(() -> {
DeviceConfig.setProperties(
new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
.setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_ALLOWLIST)
.setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_ALLOWLIST, "")
.setString(PLAYER_METRICS_APP_ALLOWLIST, TEST_PKG)
.build());
});
Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackStateEvent e =
new PlaybackStateEvent.Builder()
.setTimeSinceCreatedMillis(1763L)
.setState(PlaybackStateEvent.STATE_JOINING_FOREGROUND)
.setMetricsBundle(new Bundle())
.build();
s.reportPlaybackStateEvent(e);
writeSessionIdToFile(s.getSessionId().getStringId());
resetProperties();
}
@Test
public void testAttributionAllowlist() throws Exception {
SystemUtil.runWithShellPermissionIdentity(() -> {
DeviceConfig.setProperties(
new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_MEDIA)
.setString(MEDIA_METRICS_MODE, MEDIA_METRICS_MODE_ALLOWLIST)
.setString(PLAYER_METRICS_PER_APP_ATTRIBUTION_ALLOWLIST, TEST_PKG)
.setString(PLAYER_METRICS_APP_ALLOWLIST, "")
.build());
});
Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
Context context = InstrumentationRegistry.getInstrumentation().getContext();
MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
PlaybackSession s = manager.createPlaybackSession();
PlaybackMetrics e =
new PlaybackMetrics.Builder()
.setMediaDurationMillis(233L)
.setStreamSource(PlaybackMetrics.STREAM_SOURCE_NETWORK)
.setStreamType(PlaybackMetrics.STREAM_TYPE_OTHER)
.setPlaybackType(PlaybackMetrics.PLAYBACK_TYPE_LIVE)
.setDrmType(PlaybackMetrics.DRM_TYPE_WIDEVINE_L1)
.setContentType(PlaybackMetrics.CONTENT_TYPE_MAIN)
.setPlayerName("ExoPlayer")
.setPlayerVersion("1.01x")
.setVideoFramesPlayed(1024)
.setVideoFramesDropped(32)
.setAudioUnderrunCount(22)
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
.setDrmSessionId(new byte[] {2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
s.reportPlaybackMetrics(e);
writeSessionIdToFile(s.getSessionId().getStringId());
resetProperties();
}
/**
* Open aaudio low latency output stream and then close
*/
@Test
public native void testAAudioLowLatencyOutputStream();
/**
* Open aaudio low latency input stream and then close
*/
@Test
public native void testAAudioLowLatencyInputStream();
/**
* Open aaudio legacy output stream and then close
*/
@Test
public native void testAAudioLegacyOutputStream();
/**
* Open aaudio legacy input stream and then close
*/
@Test
public native void testAAudioLegacyInputStream();
private void writeSessionIdToFile(String stringId) throws IOException {
// TODO(b/259258249): Name session id after the test.
Context context = InstrumentationRegistry.getInstrumentation().getContext();
Log.i(TAG, "log_session_id=" + stringId);
File logDir = context.getExternalFilesDir(null);
File logFile = new File(logDir, "log_session_id.txt");
logFile.createNewFile();
FileWriter fw = new FileWriter(logFile.getAbsolutePath());
fw.write(stringId);
fw.close();
Log.i(TAG, "Logged to " + logFile.getAbsolutePath());
}
}