mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Feat] (Android): the render server screen and binary ship in the plugin APK too, not just trace
This commit is contained in:
@@ -61,6 +61,24 @@ if ! grep -Eq '^lib/[^/]+/libMobileGL\.so$' <<<"$plugin_contents"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The render server is not trace-only: both flavors carry the control screen, the offscreen
|
||||
# service, the on-screen display activity, and (split native builds) the supervisor executable.
|
||||
# The plugin APK ships to users, so its build keeps the three components private (manifest
|
||||
# placeholder serverComponentsExported=false); only the debuggable trace APK exports them for adb.
|
||||
for component in ServerControlActivity MobileGLServerService MobileGLDisplayActivity; do
|
||||
require "$component" "$plugin_manifest" "plugin render server component ($component)"
|
||||
require "$component" "$trace_manifest" "trace render server component ($component)"
|
||||
done
|
||||
if [[ "${MOBILEGL_CI_DISAGGREGATED:-OFF}" == "ON" ]]; then
|
||||
trace_contents=$(unzip -Z1 "$trace_apk")
|
||||
for entry in "plugin:${plugin_contents}" "trace:${trace_contents}"; do
|
||||
if ! grep -Eq '^lib/[^/]+/libMobileGLServer\.so$' <<<"${entry#*:}"; then
|
||||
echo "::error::${entry%%:*} APK does not contain libMobileGLServer.so (both flavors ship the render server)" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
require 'top.mobilegl.plugin.trace' "$trace_manifest" 'trace package name'
|
||||
require 'top.mobilegl.plugin.TRACE_REPLAY' "$trace_manifest" 'trace replay action'
|
||||
if grep -Fq 'fclPlugin' <<<"$trace_manifest"; then
|
||||
|
||||
+1
-1
@@ -682,7 +682,7 @@ if (ANDROID)
|
||||
MobileGL/MG_Util/SelfTest/DriverBenchJni.cpp
|
||||
)
|
||||
if (MOBILEGL_BUILD_DISAGGREGATED)
|
||||
# P12 (on-screen server window): the trace APK's MobileGLDisplayActivity - the in-process
|
||||
# P12 (on-screen server window): the APK's MobileGLDisplayActivity - the in-process
|
||||
# display server's thread, its SurfaceView's ANativeWindow in and out of ServerDisplay, and
|
||||
# the geometry up-call. Split build only: nothing else has an in-process server to drive.
|
||||
list(APPEND SOURCE_FILES
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// P12 (on-screen server window), D3/D5/D6/D7. THE JNI GLUE OF THE IN-PROCESS DISPLAY SERVER.
|
||||
//
|
||||
// The trace APK's MobileGLDisplayActivity (android:process=":mglwin") owns a SurfaceView and runs
|
||||
// The APK's MobileGLDisplayActivity (android:process=":mglwin") owns a SurfaceView and runs
|
||||
// the TCP server on a thread of its own process, so a headless client (MOBILEGL_IPC_SURFACE=server)
|
||||
// renders straight onto that SurfaceView. This file is the whole native half of that Activity:
|
||||
//
|
||||
|
||||
@@ -35,7 +35,10 @@ fun Project.mobileGlCmakeCompilerLauncher(): String =
|
||||
|
||||
// Match the native module's two switches, including INPROC implying the parent
|
||||
// option. A D/P plugin must ask its launcher to select the transport at runtime;
|
||||
// compiling MG_Remote alone leaves ConfigLoader's default on monolith.
|
||||
// compiling MG_Remote alone leaves ConfigLoader's default on monolith. The native module
|
||||
// builds the split shape by default in a standalone build (it carries the render server),
|
||||
// so this is only the opt-in for the launcher-selected in-process TRANSPORT: unset, the
|
||||
// plugin still runs monolith.
|
||||
fun Project.mobileGlDisaggregatedEnabled(): Boolean {
|
||||
fun enabled(value: Any?): Boolean = value?.toString()?.trim()?.uppercase().orEmpty() in setOf("1", "ON", "YES", "TRUE", "Y")
|
||||
return enabled(findProperty("mobilegl.buildDisaggregated") ?: System.getenv("MOBILEGL_BUILD_DISAGGREGATED")) ||
|
||||
@@ -172,11 +175,17 @@ android {
|
||||
productFlavors {
|
||||
create("plugin") {
|
||||
dimension = "profile"
|
||||
// The shipped renderer plugin keeps its render-server components private; the
|
||||
// screen and NavBar start them from inside the app.
|
||||
manifestPlaceholders["serverComponentsExported"] = "false"
|
||||
}
|
||||
create("trace") {
|
||||
dimension = "profile"
|
||||
applicationIdSuffix = ".trace"
|
||||
versionNameSuffix = "-trace"
|
||||
// Debuggable dev APK: adb (tcp_device_server.py, the CI TCP lane) starts the
|
||||
// server components directly by explicit component name.
|
||||
manifestPlaceholders["serverComponentsExported"] = "true"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- The render server (ServerControlActivity / MobileGLServerService /
|
||||
MobileGLDisplayActivity): a TCP listener kept alive by a wake lock in a data-sync
|
||||
foreground service. -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
|
||||
<application
|
||||
android:hasCode="true"
|
||||
android:label="${appLabel}"
|
||||
@@ -22,6 +30,41 @@
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.MobileGLPlugin.NoDisplay" />
|
||||
|
||||
<!-- Render server control screen: start/stop the offscreen TCP supervisor
|
||||
(MobileGLServerService) or the on-screen display server. Not a launcher: the
|
||||
bottom navigation bar (NavBar) switches between it and PostActivity. Both flavors
|
||||
ship the server (libMobileGLServer.so + the display server's JNI in libMobileGL.so).
|
||||
serverComponentsExported: the trace flavor is a debuggable dev APK that adb drives by
|
||||
explicit component (listen/token/env/onscreen/start/stop extras), so it exports
|
||||
them. The plugin flavor ships to users, and an exported component would let any app
|
||||
on the device start a server with an env of its own choosing. singleTop delivers the
|
||||
adb extras to a running screen through onNewIntent. -->
|
||||
<activity
|
||||
android:name=".ServerControlActivity"
|
||||
android:exported="${serverComponentsExported}"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/Theme.MobileGLPlugin" />
|
||||
<service
|
||||
android:name=".MobileGLServerService"
|
||||
android:exported="${serverComponentsExported}"
|
||||
android:foregroundServiceType="dataSync"
|
||||
android:process=":mglsrv" />
|
||||
<!-- P12 (on-screen server window): the ON-SCREEN display server. Its own process (:mglwin)
|
||||
runs the TCP server on a thread and renders a headless client's window surface
|
||||
(MOBILEGL_IPC_SURFACE=server) onto its SurfaceView. One server at a time: starting it
|
||||
stops MobileGLServerService, starting the service kills :mglwin. Software window
|
||||
rendering keeps HWUI off EGL here (Espryt's teardown terminates the default display);
|
||||
configChanges keeps the Surface through rotation and overlay changes. -->
|
||||
<activity
|
||||
android:name=".MobileGLDisplayActivity"
|
||||
android:configChanges="@integer/trace_replay_config_changes"
|
||||
android:exported="${serverComponentsExported}"
|
||||
android:hardwareAccelerated="false"
|
||||
android:launchMode="singleTop"
|
||||
android:process=":mglwin"
|
||||
android:taskAffinity="${applicationId}.mglwin"
|
||||
android:theme="@style/Theme.MobileGLPlugin" />
|
||||
|
||||
<!-- One benchmark run per process: the backend is latched at MobileGL
|
||||
init and Espryt teardown kills the process-default EGL display, so
|
||||
the bench must never share a process with the POST UI. The service
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Trace-only entry point for a TCP supervisor; EGL belongs to its session children. */
|
||||
/** Entry point for the offscreen TCP supervisor; EGL belongs to its session children. */
|
||||
public final class MobileGLServerService extends Service {
|
||||
private static final String TAG = "MobileGLServer";
|
||||
private static final String CHANNEL = "mobilegl-server";
|
||||
@@ -10,11 +10,9 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Bottom navigation bar switching between the dev screens (POST and the render
|
||||
* server control). The bar only appears in flavors that ship both screens: the
|
||||
* plugin flavor has no ServerControlActivity, so wrap() returns the content
|
||||
* unchanged there. Tabs switch by reordering the other activity to the front,
|
||||
* so each screen keeps its state while the other is open.
|
||||
* Bottom navigation bar switching between the POST screen and the render server
|
||||
* control screen. Tabs switch by reordering the other activity to the front, so each
|
||||
* screen keeps its state while the other is open.
|
||||
*/
|
||||
public final class NavBar {
|
||||
public static final int TAB_POST = 0;
|
||||
@@ -25,19 +23,10 @@ public final class NavBar {
|
||||
private static final int COLOR_TAB_INACTIVE = 0xFF9E9E9E;
|
||||
private static final int BAR_HEIGHT_DP = 56;
|
||||
|
||||
private static final String SERVER_ACTIVITY = "top.mobilegl.plugin.ServerControlActivity";
|
||||
|
||||
private NavBar() {}
|
||||
|
||||
/** Returns content wrapped with the bottom bar, or content unchanged in plugin builds. */
|
||||
/** Returns content wrapped with the bottom bar. */
|
||||
public static View wrap(Activity activity, View content, int currentTab) {
|
||||
final Class<?> serverClass;
|
||||
try {
|
||||
serverClass = Class.forName(SERVER_ACTIVITY);
|
||||
} catch (ClassNotFoundException notInThisFlavor) {
|
||||
return content;
|
||||
}
|
||||
|
||||
LinearLayout root = new LinearLayout(activity);
|
||||
root.setOrientation(LinearLayout.VERTICAL);
|
||||
root.addView(content, new LinearLayout.LayoutParams(
|
||||
@@ -47,7 +36,7 @@ public final class NavBar {
|
||||
bar.setOrientation(LinearLayout.HORIZONTAL);
|
||||
bar.setBackgroundColor(COLOR_BAR);
|
||||
addTab(activity, bar, "POST", PostActivity.class, currentTab == TAB_POST);
|
||||
addTab(activity, bar, "Render Server", serverClass, currentTab == TAB_SERVER);
|
||||
addTab(activity, bar, "Render Server", ServerControlActivity.class, currentTab == TAB_SERVER);
|
||||
root.addView(bar, new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, dp(activity, BAR_HEIGHT_DP)));
|
||||
return root;
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The server role's environment, shared by the two servers the trace APK can run.
|
||||
* The server role's environment, shared by the two servers the APK can run.
|
||||
*
|
||||
* <p>{@link MobileGLServerService} exec's the offscreen supervisor with it (a ProcessBuilder
|
||||
* environment); {@link MobileGLDisplayActivity} applies it to its OWN process with Os.setenv /
|
||||
@@ -2,42 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
|
||||
<application>
|
||||
<!-- Render server control screen: start/stop the offscreen TCP supervisor
|
||||
(MobileGLServerService) or the on-screen display server. Not the launcher:
|
||||
PostActivity is the entry icon and the bottom navigation bar switches between
|
||||
the two screens; exported so adb can drive it by explicit component with
|
||||
listen/token/env/onscreen/start/stop extras. -->
|
||||
<activity
|
||||
android:name=".ServerControlActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/Theme.MobileGLPlugin" />
|
||||
<service
|
||||
android:name=".MobileGLServerService"
|
||||
android:exported="true"
|
||||
android:foregroundServiceType="dataSync"
|
||||
android:process=":mglsrv" />
|
||||
<!-- P12 (on-screen server window): the ON-SCREEN display server. Its own process (:mglwin)
|
||||
runs the TCP server on a thread and renders a headless client's window surface
|
||||
(MOBILEGL_IPC_SURFACE=server) onto its SurfaceView. One server at a time: starting it
|
||||
stops MobileGLServerService, starting the service kills :mglwin. Software window
|
||||
rendering keeps HWUI off EGL here (Espryt's teardown terminates the default display);
|
||||
configChanges keeps the Surface through rotation and overlay changes. -->
|
||||
<activity
|
||||
android:name=".MobileGLDisplayActivity"
|
||||
android:configChanges="@integer/trace_replay_config_changes"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="false"
|
||||
android:launchMode="singleTop"
|
||||
android:process=":mglwin"
|
||||
android:taskAffinity="${applicationId}.mglwin"
|
||||
android:theme="@style/Theme.MobileGLPlugin" />
|
||||
<activity
|
||||
android:name=".PluginActivity"
|
||||
tools:node="remove" />
|
||||
|
||||
@@ -30,9 +30,13 @@ subprojects {
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
// P5 trace A/B: :MobileGL owns libMobileGL.so, not :app's replay runner.
|
||||
// Both flavors ship the render server, so the split shape is on by default
|
||||
// (-Pmobilegl.buildDisaggregated=OFF opts out); INPROC follows it, as in
|
||||
// MobileGL/build.gradle.
|
||||
val disaggregated = project.findProperty("mobilegl.buildDisaggregated") ?: "ON"
|
||||
arguments += listOf(
|
||||
"-DMOBILEGL_BUILD_DISAGGREGATED=${project.findProperty("mobilegl.buildDisaggregated") ?: "OFF"}",
|
||||
"-DMOBILEGL_BUILD_DISAGGREGATED_INPROC=${project.findProperty("mobilegl.buildDisaggregatedInproc") ?: "OFF"}",
|
||||
"-DMOBILEGL_BUILD_DISAGGREGATED=$disaggregated",
|
||||
"-DMOBILEGL_BUILD_DISAGGREGATED_INPROC=${project.findProperty("mobilegl.buildDisaggregatedInproc") ?: disaggregated}",
|
||||
)
|
||||
mobileGlCmakeCompilerLauncher().takeIf(String::isNotEmpty)?.let { compilerLauncher ->
|
||||
arguments += listOf(
|
||||
|
||||
+9
-3
@@ -23,13 +23,19 @@ def mobileGlBuildServerSpike = {
|
||||
(rootProject.findProperty('mobilegl.buildServerSpike') ?: System.getenv('MOBILEGL_BUILD_SERVER_SPIKE') ?: 'OFF') as String
|
||||
}
|
||||
|
||||
// Shared native shape for BOTH plugin and trace APKs. Defaults keep existing
|
||||
// callers on pull; disaggregated CI explicitly selects all three switches.
|
||||
// Shared native shape for BOTH plugin and trace APKs. The render server (libMobileGLServer.so and
|
||||
// the display server's JNI) is part of the split shape, and both flavors of a standalone plugin
|
||||
// build ship it, so there the split shape is ON unless a build opts out with
|
||||
// -Pmobilegl.buildDisaggregated=OFF. The runtime transport is unaffected: the app's
|
||||
// MOBILEGL_TRANSPORT env stays opt-in (app/build.gradle.kts), so the monolith path is still the
|
||||
// default. The FCL-embedded library keeps its old defaults (pull, no MG_Remote): FCL packages
|
||||
// neither the server nor its screen.
|
||||
// Disaggregated CI explicitly selects all three switches.
|
||||
def mobileGlPipePush = {
|
||||
(rootProject.findProperty('mobilegl.pipePush') ?: System.getenv('MOBILEGL_PIPE_PUSH_APK') ?: 'OFF') as String
|
||||
}
|
||||
def mobileGlBuildDisaggregated = {
|
||||
(rootProject.findProperty('mobilegl.buildDisaggregated') ?: System.getenv('MOBILEGL_BUILD_DISAGGREGATED') ?: 'OFF') as String
|
||||
(rootProject.findProperty('mobilegl.buildDisaggregated') ?: System.getenv('MOBILEGL_BUILD_DISAGGREGATED') ?: (standalonePluginBuild ? 'ON' : 'OFF')) as String
|
||||
}
|
||||
def mobileGlBuildDisaggregatedInproc = {
|
||||
(rootProject.findProperty('mobilegl.buildDisaggregatedInproc') ?: System.getenv('MOBILEGL_BUILD_DISAGGREGATED_INPROC') ?: mobileGlBuildDisaggregated()) as String
|
||||
|
||||
@@ -31,6 +31,6 @@ ctest --test-dir build-split -L 'integration-(spawn|tcp)' --output-on-failure
|
||||
## Android
|
||||
|
||||
- 三份 APK flavour:pull / push / split(Gradle 属性 `mobilegl.pipePush`、`mobilegl.buildDisaggregated`、`mobilegl.buildDisaggregatedInproc`)。split APK 同样要设 `MOBILEGL_TRANSPORT`,不设就是单进程对照。
|
||||
- 设备侧 server 有两种形态:离屏的前台 Service(`MobileGLServerService`)与上屏的 `MobileGLDisplayActivity`;同一时刻只有一个。
|
||||
- 设备侧 server 有两种形态:离屏的前台 Service(`MobileGLServerService`)与上屏的 `MobileGLDisplayActivity`;同一时刻只有一个。plugin 与 trace 两个 flavour 的 APK 都带(standalone 构建默认开 `mobilegl.buildDisaggregated`),入口是 APK 底部导航栏的 “Render Server” 页;plugin flavour 的这三个组件不导出,只有 trace 允许 adb 直接按组件名拉起。
|
||||
- 电脑当 client、手机当 server 的跨机配置(起 server、设令牌、`adb forward` 备用路线)见 [`../notes/p65/README.md`](../notes/p65/README.md) 的"两边怎么配"。
|
||||
- 性能对比只用 Redmi `2f7cbe2e`,按 [`pin-verification-2026-09-07.md`](pin-verification-2026-09-07.md) 定频,reboot-clean、同热窗口、配对 A/B。
|
||||
|
||||
@@ -9,14 +9,16 @@ import xml.etree.ElementTree as ET
|
||||
|
||||
def main():
|
||||
root = pathlib.Path(__file__).resolve().parents[2]
|
||||
trace = root / "android-plugin/app/src/trace"
|
||||
src = root / "android-plugin/app/src"
|
||||
trace = src / "trace"
|
||||
main_src = src / "main"
|
||||
android = "{http://schemas.android.com/apk/res/android}"
|
||||
manifest = ET.parse(trace / "AndroidManifest.xml")
|
||||
activity = next(a for a in manifest.findall("application/activity")
|
||||
if a.get(android + "name") == ".trace.TraceReplayActivity")
|
||||
config_value = activity.get(android + "configChanges", "0")
|
||||
if config_value == "@integer/trace_replay_config_changes":
|
||||
resources = ET.parse(trace / "res/values/config.xml")
|
||||
resources = ET.parse(main_src / "res/values/config.xml")
|
||||
config_value = resources.find("integer[@name='trace_replay_config_changes']").text
|
||||
changes = int(config_value, 0)
|
||||
# The failing emulator added resource overlays after replay had already started.
|
||||
@@ -31,34 +33,52 @@ def main():
|
||||
# finds it by this name to enforce one server at a time), software window rendering (HWUI must
|
||||
# not share the EGL display Espryt terminates), and the same configChanges as the replay
|
||||
# Activity (a rotation or an overlay must not destroy the window a session renders into).
|
||||
display = next((a for a in manifest.findall("application/activity")
|
||||
# The render server ships in BOTH flavors, so these components live in the main manifest.
|
||||
# exported is a manifest placeholder (true for the adb-driven trace flavor, false for the
|
||||
# plugin flavor that ships to users); a literal "true" here would export it from the plugin.
|
||||
exported_placeholder = "${serverComponentsExported}"
|
||||
main_manifest = ET.parse(main_src / "AndroidManifest.xml")
|
||||
display = next((a for a in main_manifest.findall("application/activity")
|
||||
if a.get(android + "name") == ".MobileGLDisplayActivity"), None)
|
||||
if display is None:
|
||||
raise RuntimeError("the trace manifest has no MobileGLDisplayActivity (P12 D7)")
|
||||
raise RuntimeError("the main manifest has no MobileGLDisplayActivity (P12 D7)")
|
||||
for attribute, expected in (("process", ":mglwin"), ("hardwareAccelerated", "false"),
|
||||
("exported", "true"),
|
||||
("exported", exported_placeholder),
|
||||
("configChanges", activity.get(android + "configChanges"))):
|
||||
if display.get(android + attribute) != expected:
|
||||
raise RuntimeError(f"MobileGLDisplayActivity android:{attribute} must be {expected!r}, "
|
||||
f"not {display.get(android + attribute)!r}")
|
||||
# Every trace-flavour Java class that has NO android.* import belongs here, because javac
|
||||
for tag, name in (("activity", ".ServerControlActivity"), ("service", ".MobileGLServerService")):
|
||||
component = next((c for c in main_manifest.findall(f"application/{tag}")
|
||||
if c.get(android + "name") == name), None)
|
||||
if component is None:
|
||||
raise RuntimeError(f"the main manifest has no {name}")
|
||||
if component.get(android + "exported") != exported_placeholder:
|
||||
raise RuntimeError(f"{name} android:exported must be {exported_placeholder!r}, "
|
||||
f"not {component.get(android + 'exported')!r}")
|
||||
# The trace manifest must not redeclare them: a second declaration would override the placeholder.
|
||||
for tag, name in (("activity", ".ServerControlActivity"), ("service", ".MobileGLServerService"),
|
||||
("activity", ".MobileGLDisplayActivity")):
|
||||
if any(c.get(android + "name") == name for c in manifest.findall(f"application/{tag}")):
|
||||
raise RuntimeError(f"the trace manifest redeclares {name}; it belongs to the main manifest")
|
||||
# Every Java class that has NO android.* import belongs here, because javac
|
||||
# plus `java` is the only way any of them is exercised outside an APK on a device. P7 added
|
||||
# SpawnServerPath: a hand-rolled K=V;K=V parse whose failure mode on device is "the knob had
|
||||
# no effect", which is why a defect in it survived from P6. P12 added ServerEnvironment: the
|
||||
# server role's environment both servers build (the service's exec environment, the display
|
||||
# Activity's own process) and the display's aspect-fit.
|
||||
java_units = [
|
||||
("top.mobilegl.plugin.trace", "TraceReplaySession", "TraceReplaySessionTest"),
|
||||
("top.mobilegl.plugin.trace", "SpawnServerPath", "SpawnServerPathTest"),
|
||||
("top.mobilegl.plugin", "ServerEnvironment", "ServerEnvironmentTest"),
|
||||
(trace, "top.mobilegl.plugin.trace", "TraceReplaySession", "TraceReplaySessionTest"),
|
||||
(trace, "top.mobilegl.plugin.trace", "SpawnServerPath", "SpawnServerPathTest"),
|
||||
(main_src, "top.mobilegl.plugin", "ServerEnvironment", "ServerEnvironmentTest"),
|
||||
]
|
||||
with tempfile.TemporaryDirectory(prefix="mobilegl-replay-lifecycle-") as output:
|
||||
sources = []
|
||||
for package, unit, test in java_units:
|
||||
sources.append(str(trace / "java" / package.replace(".", "/") / f"{unit}.java"))
|
||||
for source_set, package, unit, test in java_units:
|
||||
sources.append(str(source_set / "java" / package.replace(".", "/") / f"{unit}.java"))
|
||||
sources.append(str(root / f"tools/trace_replay/{test}.java"))
|
||||
subprocess.run(["javac", "--release", "11", "-d", output, *sources], check=True)
|
||||
for package, _, test in java_units:
|
||||
for _, package, _, test in java_units:
|
||||
subprocess.run(["java", "-cp", output, f"{package}.{test}"], check=True)
|
||||
print("Android replay manifest and lifecycle checks passed")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user