Move STS utilities out of CTS.

Test: m sts
Bug: 238373261

Change-Id: Ib2693ec8b5bd8fa9e08bcdd5a924186615a0c6d8
diff --git a/apps/MainlineModuleDetector/Android.bp b/apps/MainlineModuleDetector/Android.bp
deleted file mode 100644
index 2cba39f..0000000
--- a/apps/MainlineModuleDetector/Android.bp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (C) 2019 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 {
-    // See: http://go/android-license-faq
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_test {
-    name: "MainlineModuleDetector",
-    defaults: ["cts_defaults"],
-    static_libs: ["compatibility-device-util-axt"],
-    // Disable dexpreopt and <uses-library> check for test.
-    enforce_uses_libs: false,
-    dex_preopt: {
-        enabled: false,
-    },
-    srcs: ["src/**/*.java"],
-    sdk_version: "current",
-    test_suites: [
-        "cts",
-        "general-tests",
-        "sts",
-    ],
-}
diff --git a/apps/MainlineModuleDetector/AndroidManifest.xml b/apps/MainlineModuleDetector/AndroidManifest.xml
deleted file mode 100644
index dce1cae..0000000
--- a/apps/MainlineModuleDetector/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-     package="com.android.cts.mainlinemoduledetector"
-     android:versionCode="1"
-     android:versionName="1.0">
-
-    <application>
-        <activity android:name=".MainlineModuleDetector"
-             android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.LAUNCHER"/>
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/apps/MainlineModuleDetector/OWNERS b/apps/MainlineModuleDetector/OWNERS
deleted file mode 100644
index 9d3e569..0000000
--- a/apps/MainlineModuleDetector/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 195645
-manjaepark@google.com
-mspector@google.com
-duytruong@google.com
-cdombroski@google.com
diff --git a/apps/MainlineModuleDetector/src/com/android/cts/mainlinemoduledetector/MainlineModuleDetector.java b/apps/MainlineModuleDetector/src/com/android/cts/mainlinemoduledetector/MainlineModuleDetector.java
deleted file mode 100644
index 01c02c7..0000000
--- a/apps/MainlineModuleDetector/src/com/android/cts/mainlinemoduledetector/MainlineModuleDetector.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.android.cts.mainlinemoduledetector;
-
-import android.app.Activity;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.compatibility.common.util.mainline.MainlineModule;
-import com.android.compatibility.common.util.mainline.ModuleDetector;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class MainlineModuleDetector extends Activity {
-
-    private static final String LOG_TAG = "MainlineModuleDetector";
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        try {
-            PackageManager pm = getApplicationContext().getPackageManager();
-            Set<MainlineModule> modules = ModuleDetector.getPlayManagedModules(pm);
-            Set<String> moduleNames = new HashSet<>();
-            for (MainlineModule module : modules) {
-                moduleNames.add(module.packageName);
-            }
-            Log.i(LOG_TAG, "Play managed modules are: <" + String.join(",", moduleNames) + ">");
-        } catch (Exception e) {
-            Log.e(LOG_TAG, "Failed to retrieve modules.", e);
-        }
-        this.finish();
-    }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/HostsideMainlineModuleDetector.java b/hostsidetests/securitybulletin/src/android/security/cts/HostsideMainlineModuleDetector.java
deleted file mode 100644
index 1d57cb6..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/HostsideMainlineModuleDetector.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 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.security.cts;
-
-import com.android.ddmlib.Log;
-
-import com.google.common.collect.ImmutableSet;
-
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class HostsideMainlineModuleDetector {
-    private static final String LOG_TAG = "MainlineModuleDetector";
-
-    private SecurityTestCase context;
-
-    private static ImmutableSet<String> playManagedModules;
-
-    HostsideMainlineModuleDetector(SecurityTestCase context) {
-        this.context = context;
-    }
-
-    synchronized Set<String> getPlayManagedModules() throws Exception {
-        if (playManagedModules == null) {
-            AdbUtils.runCommandLine("logcat -c", context.getDevice());
-            String output = AdbUtils.runCommandLine(
-                    "am start com.android.cts.mainlinemoduledetector/.MainlineModuleDetector",
-                    context.getDevice());
-            Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG,
-                    "am output: " + output);
-            Thread.sleep(5 * 1000L);
-            String logcat = AdbUtils.runCommandLine("logcat -d -s MainlineModuleDetector:I",
-                    context.getDevice());
-            Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG,
-                    "Found logcat output: " + logcat);
-            Matcher matcher = Pattern.compile("Play managed modules are: <(.*?)>").matcher(logcat);
-            if (matcher.find()) {
-                playManagedModules = ImmutableSet.copyOf(matcher.group(1).split(","));
-            } else {
-                playManagedModules = ImmutableSet.of();
-            }
-        }
-        return playManagedModules;
-    }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java b/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java
deleted file mode 100644
index 07f45db..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2020 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.security.cts;
-
-
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.io.File;
-import java.io.FileNotFoundException;
-
-import org.junit.runner.Description;
-import org.junit.rules.TestWatcher;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.IAbi;
-
-import static org.junit.Assume.*;
-import static org.junit.Assert.*;
-
-public class PocPusher extends TestWatcher {
-    private ITestDevice device = null;
-    private CompatibilityBuildHelper buildHelper = null;
-    private IAbi abi = null;
-
-    private Set<String> filesToCleanup = new HashSet();
-    public boolean bitness32 = true;
-    public boolean bitness64 = true;
-    public boolean appendBitness = true;
-    public boolean cleanup = true;
-
-    @Override
-    protected void starting(Description d) {
-        bothBitness();
-        appendBitness = true;
-        cleanup = true;
-    }
-
-    @Override
-    protected void finished(Description d) {
-        for (Iterator<String> it = filesToCleanup.iterator(); it.hasNext();) {
-            String file = it.next();
-            try {
-                CLog.i("Cleaning up %s", file);
-                device.deleteFile(file);
-            } catch (DeviceNotAvailableException e) {
-                CLog.e("Device unavailable when cleaning up %s", file);
-                continue; // try to remove next time
-            }
-            it.remove();
-        }
-    }
-
-    public PocPusher setDevice(ITestDevice device) {
-        this.device = device;
-        return this;
-    }
-
-    public PocPusher setAbi(IAbi abi) {
-        this.abi = abi;
-        return this;
-    }
-
-    public PocPusher setBuild(IBuildInfo buildInfo) {
-        buildHelper = new CompatibilityBuildHelper(buildInfo);
-        return this;
-    }
-
-    public PocPusher appendBitness(boolean append) {
-        this.appendBitness = append;
-        return this;
-    }
-
-    public PocPusher cleanup(boolean cleanup) {
-        this.cleanup = cleanup;
-        return this;
-    }
-
-    public PocPusher only32() {
-        bitness32 = true;
-        bitness64 = false;
-        return this;
-    }
-
-    public PocPusher only64() {
-        bitness32 = false;
-        bitness64 = true;
-        return this;
-    }
-
-    public PocPusher bothBitness() {
-        bitness32 = true;
-        bitness64 = true;
-        return this;
-    }
-
-    public void pushFile(String testFile, String remoteFile)
-            throws FileNotFoundException, DeviceNotAvailableException {
-        if (appendBitness) {
-            // if neither 32 or 64, nothing would ever be pushed.
-            assertTrue("bitness must be 32, 64, or both.", bitness32 || bitness64);
-
-            String bitness = SecurityTestCase.getAbi(device).getBitness().trim();
-
-            // 32-bit doesn't have a 64-bit compatibility layer; skipping.
-            assumeFalse(bitness.equals("32") && !bitness32);
-
-            // push the 32-bit file on 64-bit device if a 64-bit file doesn't exist.
-            if (bitness.equals("64") && !bitness64) {
-                bitness = "32";
-                CLog.i("Pushing a 32-bit file onto a 64-bit device.");
-            }
-            testFile += bitness;
-        }
-        CLog.i("Pushing local: %s to remote: %s", testFile.toString(), remoteFile);
-        File localFile = buildHelper.getTestFile(testFile);
-        device.pushFile(localFile, remoteFile);
-        if (cleanup) {
-            filesToCleanup.add(remoteFile);
-        }
-    }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java
deleted file mode 100644
index 9ce7e39..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2019 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.security.cts;
-
-import java.util.concurrent.TimeoutException;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import static org.junit.Assert.*;
-
-public class RegexUtils {
-    private static final int TIMEOUT_DURATION = 20 * 60_000; // 20 minutes
-    private static final int WARNING_THRESHOLD = 1000; // 1 second
-    private static final int CONTEXT_RANGE = 100; // chars before/after matched input string
-
-    public static void assertContains(String pattern, String input) throws Exception {
-        assertFind(pattern, input, false, false);
-    }
-
-    public static void assertContainsMultiline(String pattern, String input) throws Exception {
-        assertFind(pattern, input, false, true);
-    }
-
-    public static void assertNotContains(String pattern, String input) throws Exception {
-        assertFind(pattern, input, true, false);
-    }
-
-    public static void assertNotContainsMultiline(String pattern, String input) throws Exception {
-        assertFind(pattern, input, true, true);
-    }
-
-    private static void assertFind(
-            String pattern, String input, boolean shouldFind, boolean multiline) {
-        // The input string throws an error when used after the timeout
-        TimeoutCharSequence timedInput = new TimeoutCharSequence(input, TIMEOUT_DURATION);
-        Matcher matcher = null;
-        if (multiline) {
-            // DOTALL lets .* match line separators
-            // MULTILINE lets ^ and $ match line separators instead of input start and end
-            matcher = Pattern.compile(
-                    pattern, Pattern.DOTALL|Pattern.MULTILINE).matcher(timedInput);
-        } else {
-            matcher = Pattern.compile(pattern).matcher(timedInput);
-        }
-
-        try {
-            long start = System.currentTimeMillis();
-            boolean found = matcher.find();
-            long duration = System.currentTimeMillis() - start;
-
-            if (duration > WARNING_THRESHOLD) {
-                // Provide a warning to the test developer that their regex should be optimized.
-                CLog.logAndDisplay(LogLevel.WARN, "regex match took " + duration + "ms.");
-            }
-
-            if (found && shouldFind) { // failed notContains
-                String substring = input.substring(matcher.start(), matcher.end());
-                String context = getInputContext(input, matcher.start(), matcher.end(),
-                        CONTEXT_RANGE, CONTEXT_RANGE);
-                fail("Pattern found: '" + pattern + "' -> '" + substring + "' for input:\n..." +
-                        context + "...");
-            } else if (!found && !shouldFind) { // failed contains
-                fail("Pattern not found: '" + pattern + "' for input:\n..." + input + "...");
-            }
-        } catch (TimeoutCharSequence.CharSequenceTimeoutException e) {
-            // regex match has taken longer than the timeout
-            // this usually means the input is extremely long or the regex is catastrophic
-            fail("Regex timeout with pattern: '" + pattern + "' for input:\n..." + input + "...");
-        }
-    }
-
-    /*
-     * Helper method to grab the nearby chars for a subsequence. Similar to the -A and -B flags for
-     * grep.
-     */
-    private static String getInputContext(String input, int start, int end, int before, int after) {
-        start = Math.max(0, start - before);
-        end = Math.min(input.length(), end + after);
-        return input.substring(start, end);
-    }
-
-    /*
-     * Wrapper for a given CharSequence. When charAt() is called, the current time is compared
-     * against the timeout. If the current time is greater than the expiration time, an exception is
-     * thrown. The expiration time is (time of object construction) + (timeout in milliseconds).
-     */
-    private static class TimeoutCharSequence implements CharSequence {
-        long expireTime = 0;
-        CharSequence chars = null;
-
-        TimeoutCharSequence(CharSequence chars, long timeout) {
-            this.chars = chars;
-            expireTime = System.currentTimeMillis() + timeout;
-        }
-
-        @Override
-        public char charAt(int index) {
-            if (System.currentTimeMillis() > expireTime) {
-                throw new CharSequenceTimeoutException(
-                        "TimeoutCharSequence was used after the expiration time.");
-            }
-            return chars.charAt(index);
-        }
-
-        @Override
-        public int length() {
-            return chars.length();
-        }
-
-        @Override
-        public CharSequence subSequence(int start, int end) {
-            return new TimeoutCharSequence(chars.subSequence(start, end),
-                    expireTime - System.currentTimeMillis());
-        }
-
-        @Override
-        public String toString() {
-            return chars.toString();
-        }
-
-        private static class CharSequenceTimeoutException extends RuntimeException {
-            public CharSequenceTimeoutException(String message) {
-                super(message);
-            }
-        }
-    }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index d7a3afc7..ddfd37c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -16,39 +16,36 @@
 
 package android.security.cts;
 
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
 import com.android.compatibility.common.util.MetricsReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
+import com.android.sts.common.HostsideMainlineModuleDetector;
+import com.android.sts.common.PocPusher;
+import com.android.sts.common.RegexUtils;
 import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
-import com.android.tradefed.testtype.IBuildReceiver;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.device.NativeDevice;
 import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.ddmlib.Log;
+import com.android.tradefed.testtype.IAbi;
 
-import org.junit.rules.TestName;
-import org.junit.Rule;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.runner.RunWith;
+import org.junit.Rule;
+import org.junit.rules.TestName;
 
-import java.util.Map;
-import java.util.HashMap;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-import java.util.concurrent.Callable;
 import java.math.BigInteger;
-
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-import static org.hamcrest.core.Is.is;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class SecurityTestCase extends StsExtraBusinessLogicHostTestBase {