blob: 9ace64ffe70ffd6359e3d6dda5ad88a3d5f04306 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package arc
import (
"context"
"path/filepath"
"strings"
"time"
"chromiumos/tast/common/media/caps"
"chromiumos/tast/common/perf"
"chromiumos/tast/ctxutil"
"chromiumos/tast/local/arc"
"chromiumos/tast/local/bundles/cros/arc/c2e2etest"
"chromiumos/tast/local/bundles/cros/arc/video"
"chromiumos/tast/local/power"
"chromiumos/tast/local/power/setup"
"chromiumos/tast/testing"
"chromiumos/tast/testing/hwdep"
)
const (
// arcFilePath must be on the sdcard because of android permissions
arcFilePath = "/sdcard/Download/c2_e2e_test/"
iterationCount = 30
iterationDuration = 10 * time.Second
warmupDuration = 10 * time.Second
// Mostly consumed by boot timeout and WaitUntilIdle
testSlack = 5 * time.Minute
powerTestDuration = iterationCount*iterationDuration + warmupDuration + testSlack
logFileName = "gtest_logs.txt"
)
func init() {
testing.AddTest(&testing.Test{
Func: PowerVideoDecodePerf,
Desc: "Measures the battery drain during hardware accelerated video playback",
Contacts: []string{
"stevensd@chromium.org",
"arcvm-eng@google.com",
},
SoftwareDeps: []string{"chrome"},
Data: []string{c2e2etest.X86ApkName, c2e2etest.ArmApkName},
Fixture: "arcBootedWithDisableSyncFlags",
Attr: []string{"group:crosbolt", "crosbolt_nightly"},
Timeout: powerTestDuration,
Params: []testing.Param{
// Parameters generated by power_video_decode_perf_test.go. DO NOT EDIT.
{
Name: "h264_1080p_30fps",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.h264",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeH264,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.h264", "1080p_30fps_300frames.h264.json"},
},
{
Name: "h264_1080p_30fps_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.h264",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeH264,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.h264", "1080p_30fps_300frames.h264.json"},
},
{
Name: "h264_1080p_30fps_vm",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.h264",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeH264,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.h264", "1080p_30fps_300frames.h264.json"},
},
{
Name: "h264_1080p_30fps_vm_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.h264",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeH264,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.h264", "1080p_30fps_300frames.h264.json"},
},
{
Name: "vp8_1080p_30fps",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp8.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP8,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp8.ivf", "1080p_30fps_300frames.vp8.ivf.json"},
},
{
Name: "vp8_1080p_30fps_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp8.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP8,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp8.ivf", "1080p_30fps_300frames.vp8.ivf.json"},
},
{
Name: "vp8_1080p_30fps_vm",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp8.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP8,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp8.ivf", "1080p_30fps_300frames.vp8.ivf.json"},
},
{
Name: "vp8_1080p_30fps_vm_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp8.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP8,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp8.ivf", "1080p_30fps_300frames.vp8.ivf.json"},
},
{
Name: "vp9_1080p_30fps",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp9.ivf", "1080p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_1080p_30fps_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp9.ivf", "1080p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_1080p_30fps_vm",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp9.ivf", "1080p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_1080p_30fps_vm_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_30fps_300frames.vp9.ivf", "1080p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_1080p_60fps",
Val: video.DecodeTestOptions{
TestVideo: "1080p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_60,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_60fps_600frames.vp9.ivf", "1080p_60fps_600frames.vp9.ivf.json"},
},
{
Name: "vp9_1080p_60fps_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_60,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_60fps_600frames.vp9.ivf", "1080p_60fps_600frames.vp9.ivf.json"},
},
{
Name: "vp9_1080p_60fps_vm",
Val: video.DecodeTestOptions{
TestVideo: "1080p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_60,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"1080p_60fps_600frames.vp9.ivf", "1080p_60fps_600frames.vp9.ivf.json"},
},
{
Name: "vp9_1080p_60fps_vm_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "1080p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_60,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"1080p_60fps_600frames.vp9.ivf", "1080p_60fps_600frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_30fps",
Val: video.DecodeTestOptions{
TestVideo: "2160p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"2160p_30fps_300frames.vp9.ivf", "2160p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_30fps_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "2160p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"2160p_30fps_300frames.vp9.ivf", "2160p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_30fps_vm",
Val: video.DecodeTestOptions{
TestVideo: "2160p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"2160p_30fps_300frames.vp9.ivf", "2160p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_30fps_vm_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "2160p_30fps_300frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"2160p_30fps_300frames.vp9.ivf", "2160p_30fps_300frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_60fps",
Val: video.DecodeTestOptions{
TestVideo: "2160p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K60,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"2160p_60fps_600frames.vp9.ivf", "2160p_60fps_600frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_60fps_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "2160p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K60,
"android_p",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"2160p_60fps_600frames.vp9.ivf", "2160p_60fps_600frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_60fps_vm",
Val: video.DecodeTestOptions{
TestVideo: "2160p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.ForceBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K60,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.ForceDischarge()),
ExtraData: []string{"2160p_60fps_600frames.vp9.ivf", "2160p_60fps_600frames.vp9.ivf.json"},
},
{
Name: "vp9_2160p_60fps_vm_nobatterymetrics",
Val: video.DecodeTestOptions{
TestVideo: "2160p_60fps_600frames.vp9.ivf",
BatteryDischargeMode: setup.NoBatteryDischarge,
},
ExtraSoftwareDeps: []string{
caps.HWDecodeVP9_4K60,
"android_vm",
},
ExtraHardwareDeps: hwdep.D(hwdep.NoForceDischarge()),
ExtraData: []string{"2160p_60fps_600frames.vp9.ivf", "2160p_60fps_600frames.vp9.ivf.json"},
},
},
})
}
func PowerVideoDecodePerf(ctx context.Context, s *testing.State) {
// Give cleanup actions a minute to run, even if we fail by exceeding our
// deadline.
cleanupCtx := ctx
ctx, cancel := ctxutil.Shorten(ctx, time.Minute)
defer cancel()
cr := s.FixtValue().(*arc.PreData).Chrome
tconn, err := cr.TestAPIConn(ctx)
if err != nil {
s.Fatal("Failed to create Test API connection: ", err)
}
a := s.FixtValue().(*arc.PreData).ARC
opts := s.Param().(video.DecodeTestOptions)
// Parse JSON metadata.
md, err := c2e2etest.LoadMetadata(s.DataPath(opts.TestVideo) + ".json")
if err != nil {
s.Fatal("Failed to get metadata: ", err)
}
apkName, err := c2e2etest.ApkNameForArch(ctx, a)
if err != nil {
s.Fatal("Failed to get apk: ", err)
}
testVideoDataArg, err := md.StreamDataArg(filepath.Join(arcFilePath, opts.TestVideo))
if err != nil {
s.Fatal("Failed to construct --test_video_data: ", err)
}
testArgs := []string{
testVideoDataArg,
"--loop",
"--gtest_filter=C2VideoDecoderSurfaceE2ETest.TestFPS",
}
// Add "DecoderType: video.SoftwareDecoder" to the DecodeTestOptions to use a SW decoder.
if opts.DecoderType == video.SoftwareDecoder {
testArgs = append(testArgs, "--use_sw_decoder")
}
intentExtras := []string{
"--esa", "test-args", strings.Join(testArgs, ","),
"--es", "log-file", filepath.Join(arcFilePath, logFileName)}
sup, cleanup := setup.New("video power")
defer func() {
if err := cleanup(cleanupCtx); err != nil {
s.Error("Cleanup failed: ", err)
}
}()
sup.Add(setup.PowerTest(ctx, tconn, setup.PowerTestOptions{
Wifi: setup.DisableWifiInterfaces, Battery: opts.BatteryDischargeMode, NightLight: setup.DisableNightLight}))
sup.Add(setup.InstallApp(ctx, a, s.DataPath(apkName), c2e2etest.Pkg))
for _, p := range c2e2etest.RequiredPermissions() {
sup.Add(setup.GrantAndroidPermission(ctx, a, c2e2etest.Pkg, p))
}
sup.Add(setup.AdbMkdir(ctx, a, arcFilePath))
if err := a.PushFile(ctx, s.DataPath(opts.TestVideo), arcFilePath); err != nil {
s.Fatal("Failed to push video stream to ARC: ", err)
}
// Wait until CPU is cooled down.
if _, err := power.WaitUntilCPUCoolDown(ctx, power.DefaultCoolDownConfig(power.CoolDownPreserveUI)); err != nil {
s.Fatal("CPU failed to cool down: ", err)
}
sup.Add(setup.StartActivity(ctx, tconn, a, c2e2etest.Pkg, c2e2etest.ActivityName, setup.Prefixes("-n"), setup.Suffixes(intentExtras...)))
if err := sup.Check(ctx); err != nil {
s.Fatal("Setup failed: ", err)
}
metrics, err := perf.NewTimeline(ctx, power.TestMetrics(), perf.Interval(iterationDuration))
if err != nil {
s.Fatal("Failed to build metrics: ", err)
}
s.Log("Finished setup")
if err := metrics.Start(ctx); err != nil {
s.Fatal("Failed to start metrics: ", err)
}
s.Log("Warmup: waiting a bit before starting the measurement")
if err := testing.Sleep(ctx, warmupDuration); err != nil {
s.Fatal("Failed to sleep: ", err)
}
s.Log("Starting measurement")
if err := metrics.StartRecording(ctx); err != nil {
s.Fatal("Failed to start recording: ", err)
}
if err := testing.Sleep(ctx, iterationCount*iterationDuration); err != nil {
s.Fatal("Failed to sleep: ", err)
}
p, err := metrics.StopRecording(ctx)
if err != nil {
s.Fatal("Error while recording power metrics: ", err)
}
if err := p.Save(s.OutDir()); err != nil {
s.Error("Failed saving perf data: ", err)
}
}