Adding screen recording to toggle tests

This would be a useful addition to recently added screenshots
and other artifacts which can be seen here:
https://fusion2.corp.google.com/invocations/c8c16af0-15a1-4f03-b074-4435d82193ce/artifacts

Tests classes are supposed to always have ScreenRecordRule,
but individual tests should be marked with @ScreenRecord
only during investigations because @ScreenRecord may affect
performance characteristics.

Bug: 202567877
Test: atest PlatformScenarioTests:android.platform.test.scenario.sysui.quicksettings.ToggleFlashlightOff#testToggle
Change-Id: Ib261c55a645d70d51b75fd779058c0183444eb31
diff --git a/libraries/health/rules/src/android/platform/test/rule/FailureWatcher.java b/libraries/health/rules/src/android/platform/test/rule/FailureWatcher.java
index 7940d79..3b46815 100644
--- a/libraries/health/rules/src/android/platform/test/rule/FailureWatcher.java
+++ b/libraries/health/rules/src/android/platform/test/rule/FailureWatcher.java
@@ -47,7 +47,7 @@
         onError(mDevice, description, e);
     }
 
-    static File diagFile(Description description, String prefix, String ext) {
+    public static File diagFile(Description description, String prefix, String ext) {
         return new File(
                 getInstrumentation().getTargetContext().getFilesDir(),
                 prefix
diff --git a/libraries/health/rules/src/android/platform/test/rule/ScreenRecordRule.java b/libraries/health/rules/src/android/platform/test/rule/ScreenRecordRule.java
new file mode 100644
index 0000000..fb9d052
--- /dev/null
+++ b/libraries/health/rules/src/android/platform/test/rule/ScreenRecordRule.java
@@ -0,0 +1,81 @@
+/*
+ * 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.platform.test.rule;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import androidx.test.uiautomator.UiDevice;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.io.File;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Rule which captures a screen record for a test. After adding this rule to the test class, apply
+ * the annotation @ScreenRecord to individual tests
+ */
+public class ScreenRecordRule implements TestRule {
+
+    private static final String TAG = "ScreenRecordRule";
+
+    @Override
+    public Statement apply(Statement base, Description description) {
+        if (description.getAnnotation(ScreenRecord.class) == null) {
+            return base;
+        }
+
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                Instrumentation inst = getInstrumentation();
+                UiAutomation automation = inst.getUiAutomation();
+                UiDevice device = UiDevice.getInstance(inst);
+
+                File outputFile = FailureWatcher.diagFile(description, "ScreenRecord", "mp4");
+                device.executeShellCommand("killall screenrecord");
+                ParcelFileDescriptor output =
+                        automation.executeShellCommand("screenrecord " + outputFile);
+                String screenRecordPid = device.executeShellCommand("pidof screenrecord");
+                try {
+                    base.evaluate();
+                } finally {
+                    device.executeShellCommand("kill -INT " + screenRecordPid);
+                    Log.e(TAG, "Screenrecord captured at: " + outputFile);
+                    output.close();
+                }
+                // Delete the file if the test was successful.
+                automation.executeShellCommand("rm " + outputFile);
+            }
+        };
+    }
+
+    /** Interface to indicate that the test should capture screenrecord */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface ScreenRecord {}
+}