diff --git a/src/java/com/google/devtools/mobileharness/api/model/error/InfraErrorId.java b/src/java/com/google/devtools/mobileharness/api/model/error/InfraErrorId.java index c594ac9fa3..6f6d7a1363 100644 --- a/src/java/com/google/devtools/mobileharness/api/model/error/InfraErrorId.java +++ b/src/java/com/google/devtools/mobileharness/api/model/error/InfraErrorId.java @@ -175,6 +175,7 @@ public enum InfraErrorId implements ErrorId { LAB_DEVICE_PROVIDER_GET_DEVICE_ERROR(40_478, ErrorType.INFRA_ISSUE), LAB_DEVICE_PROVIDER_DEVICE_FEATURE_SIZE_MISMATCH(40_479, ErrorType.INFRA_ISSUE), LAB_JOB_SYNC_CLOSE_TEST_ERROR(40_480, ErrorType.INFRA_ISSUE), + LAB_RPC_EXEC_TEST_DECOUPLING_NOT_SUPPORTED(40_481, ErrorType.INFRA_ISSUE), // Test engine/container: 40_701 ~ 40_800 TE_CREATE_DEVICE_HELPER_CONTAINER_DOES_NOT_HAVE(40_701, ErrorType.INFRA_ISSUE), diff --git a/src/java/com/google/devtools/mobileharness/infra/container/controller/BUILD b/src/java/com/google/devtools/mobileharness/infra/container/controller/BUILD index 8a12488946..4bfc2a5d98 100644 --- a/src/java/com/google/devtools/mobileharness/infra/container/controller/BUILD +++ b/src/java/com/google/devtools/mobileharness/infra/container/controller/BUILD @@ -64,6 +64,7 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/controller/test/model:test_execution_unit", "//src/java/com/google/devtools/mobileharness/infra/lab/controller/util:lab_file_notifier", "//src/java/com/google/devtools/mobileharness/shared/util/logging:google_logger", + "//src/java/com/google/wireless/qa/mobileharness/shared/api/device", "@maven//:com_google_code_findbugs_jsr305", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", diff --git a/src/java/com/google/devtools/mobileharness/infra/container/controller/ProxyToDirectTestRunner.java b/src/java/com/google/devtools/mobileharness/infra/container/controller/ProxyToDirectTestRunner.java index 972f77ef2a..e11b83554f 100644 --- a/src/java/com/google/devtools/mobileharness/infra/container/controller/ProxyToDirectTestRunner.java +++ b/src/java/com/google/devtools/mobileharness/infra/container/controller/ProxyToDirectTestRunner.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkState; +import com.google.common.collect.ImmutableList; import com.google.common.flogger.FluentLogger; import com.google.devtools.mobileharness.api.model.allocation.Allocation; import com.google.devtools.mobileharness.api.model.error.InfraErrorId; @@ -35,7 +36,9 @@ import com.google.devtools.mobileharness.infra.lab.proto.File.JobOrTestFileUnit; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.concurrent.GuardedBy; +import com.google.wireless.qa.mobileharness.shared.api.device.Device; import java.time.Duration; +import java.util.List; import java.util.Optional; import java.util.concurrent.CountDownLatch; @@ -86,18 +89,27 @@ public class ProxyToDirectTestRunner extends AbstractProxyTestRunner devices; + public ProxyToDirectTestRunner( TestRunnerLauncher launcher, TestExecutionUnit testExecutionUnit, Allocation allocation, + List devices, LabFileNotifier proxiedTestLabFileNotifier, TestEngineLocator testEngineLocator) throws TestRunnerLauncherConnectedException { super(launcher, testExecutionUnit, allocation); + this.devices = ImmutableList.copyOf(devices); this.proxiedTestLabFileNotifier = proxiedTestLabFileNotifier; this.testEngineLocator = testEngineLocator; } + /** Gets the devices for the test. */ + public ImmutableList getDevices() { + return devices; + } + @Override public void notifyJobOrTestFile(JobOrTestFileUnit fileUnit) { proxiedTestLabFileNotifier.notifyJobOrTestFile(fileUnit); diff --git a/src/java/com/google/devtools/mobileharness/infra/controller/device/provider/BUILD b/src/java/com/google/devtools/mobileharness/infra/controller/device/provider/BUILD index 02ee06efbc..cf78e0b272 100644 --- a/src/java/com/google/devtools/mobileharness/infra/controller/device/provider/BUILD +++ b/src/java/com/google/devtools/mobileharness/infra/controller/device/provider/BUILD @@ -72,6 +72,7 @@ java_library( name = "allocated_device_provisioning_module", srcs = ["AllocatedDeviceProvisioningModule.java"], visibility = [ + "//:omnilab_fusion", "//src/java/com/google/devtools/mobileharness/infra/lab:__subpackages__", ], deps = [ @@ -85,6 +86,7 @@ java_library( name = "local_device_provisioning_module", srcs = ["LocalDeviceProvisioningModule.java"], visibility = [ + "//:omnilab_fusion", "//src/java/com/google/devtools/mobileharness/infra/lab:__subpackages__", ], deps = [ diff --git a/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/BUILD b/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/BUILD index 2ec2469ca5..608f25e9b5 100644 --- a/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/BUILD +++ b/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/BUILD @@ -125,6 +125,7 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/controller/test/model:test_execution_result", "//src/java/com/google/devtools/mobileharness/shared/util/concurrent:callables", "//src/java/com/google/devtools/mobileharness/shared/util/logging:google_logger", + "//src/java/com/google/devtools/mobileharness/shared/util/logging:tag", "@maven//:com_google_code_findbugs_jsr305", "@maven//:com_google_guava_guava", ], @@ -142,3 +143,34 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/controller/test:direct_test_runner", ], ) + +java_library( + name = "thread_pool_launcher_provisioning_module", + srcs = ["ThreadPoolLauncherProvisioningModule.java"], + visibility = [ + "//:omnilab_fusion", + "//src/java/com/google/devtools/mobileharness/infra/lab:__pkg__", + ], + deps = [ + ":launcher_provider", + ":test_runner_thread_pool", + ":thread_pool_test_runner_launcher_provider", + "//src/java/com/google/devtools/mobileharness/shared/util/concurrent:thread_pools", + "@maven//:com_google_inject_guice", + "@maven//:javax_inject_jsr330_api", + ], +) + +java_library( + name = "local_device_launcher_provisioning_module", + srcs = ["LocalDeviceLauncherProvisioningModule.java"], + visibility = [ + "//:omnilab_fusion", + "//src/java/com/google/devtools/mobileharness/infra/lab:__pkg__", + ], + deps = [ + ":launcher_provider", + ":local_device_test_runner_launcher_provider", + "@maven//:com_google_inject_guice", + ], +) diff --git a/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/LocalDeviceLauncherProvisioningModule.java b/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/LocalDeviceLauncherProvisioningModule.java new file mode 100644 index 0000000000..43525a03df --- /dev/null +++ b/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/LocalDeviceLauncherProvisioningModule.java @@ -0,0 +1,28 @@ +/* + * Copyright 2022 Google LLC + * + * 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 + * + * https://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.google.devtools.mobileharness.infra.controller.test.launcher; + +import com.google.inject.AbstractModule; + +/** Module for providing {@link LocalDeviceTestRunnerLauncherProvider}. */ +public class LocalDeviceLauncherProvisioningModule extends AbstractModule { + + @Override + protected void configure() { + bind(LauncherProvider.class).to(LocalDeviceTestRunnerLauncherProvider.class); + } +} diff --git a/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/ThreadPoolLauncherProvisioningModule.java b/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/ThreadPoolLauncherProvisioningModule.java new file mode 100644 index 0000000000..981f798479 --- /dev/null +++ b/src/java/com/google/devtools/mobileharness/infra/controller/test/launcher/ThreadPoolLauncherProvisioningModule.java @@ -0,0 +1,39 @@ +/* + * Copyright 2022 Google LLC + * + * 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 + * + * https://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.google.devtools.mobileharness.infra.controller.test.launcher; + +import com.google.devtools.mobileharness.shared.util.concurrent.ThreadPools; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import java.util.concurrent.ExecutorService; +import javax.inject.Singleton; + +/** Module for providing {@link ThreadPoolTestRunnerLauncher}. */ +public class ThreadPoolLauncherProvisioningModule extends AbstractModule { + + @Override + protected void configure() { + bind(LauncherProvider.class).to(ThreadPoolTestRunnerLauncherProvider.class); + } + + @Provides + @Singleton + @TestRunnerThreadPool + ExecutorService provideTestRunnerThreadPool() { + return ThreadPools.createStandardThreadPool("test-runner-thread-pool"); + } +} diff --git a/src/java/com/google/devtools/mobileharness/infra/controller/test/manager/ProxyTestManager.java b/src/java/com/google/devtools/mobileharness/infra/controller/test/manager/ProxyTestManager.java index 6742cc3d95..2ad572aae4 100644 --- a/src/java/com/google/devtools/mobileharness/infra/controller/test/manager/ProxyTestManager.java +++ b/src/java/com/google/devtools/mobileharness/infra/controller/test/manager/ProxyTestManager.java @@ -92,7 +92,7 @@ public Dirs getJobDirs(String jobId, String testId) throws MobileHarnessExceptio return getProxyToDirectTestRunner(testId).getTestExecutionUnit().job().dirs(); } - private ProxyToDirectTestRunner getProxyToDirectTestRunner(String testId) + public ProxyToDirectTestRunner getProxyToDirectTestRunner(String testId) throws MobileHarnessException { ProxyTestRunner proxyTestRunner = getTestRunnerNonEmpty(testId); if (proxyTestRunner.isContainerMode()) { diff --git a/src/java/com/google/devtools/mobileharness/infra/lab/BUILD b/src/java/com/google/devtools/mobileharness/infra/lab/BUILD index 4f55d63ebb..702a2be060 100644 --- a/src/java/com/google/devtools/mobileharness/infra/lab/BUILD +++ b/src/java/com/google/devtools/mobileharness/infra/lab/BUILD @@ -70,11 +70,15 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/controller/device/config:api_config_file_processor", "//src/java/com/google/devtools/mobileharness/infra/controller/device/external:external_device_manager", "//src/java/com/google/devtools/mobileharness/infra/controller/device/external:noop_external_device_manager", + "//src/java/com/google/devtools/mobileharness/infra/controller/device/provider:allocated_device_provisioning_module", + "//src/java/com/google/devtools/mobileharness/infra/controller/device/provider:local_device_provisioning_module", "//src/java/com/google/devtools/mobileharness/infra/controller/messaging:message_sender_finder", "//src/java/com/google/devtools/mobileharness/infra/controller/messaging:messaging_manager", "//src/java/com/google/devtools/mobileharness/infra/controller/messaging:messaging_manager_holder", "//src/java/com/google/devtools/mobileharness/infra/controller/messaging:messaging_service", "//src/java/com/google/devtools/mobileharness/infra/controller/messaging:messaging_service_module", + "//src/java/com/google/devtools/mobileharness/infra/controller/test/launcher:local_device_launcher_provisioning_module", + "//src/java/com/google/devtools/mobileharness/infra/controller/test/launcher:thread_pool_launcher_provisioning_module", "//src/java/com/google/devtools/mobileharness/infra/controller/test/manager", "//src/java/com/google/devtools/mobileharness/infra/controller/test/manager:lab_direct_test_runner_util", "//src/java/com/google/devtools/mobileharness/infra/controller/test/manager:proxy_test_manager", @@ -101,6 +105,8 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/master/rpc/stub:lab_sync", "//src/java/com/google/devtools/mobileharness/infra/master/rpc/stub/grpc:job_sync", "//src/java/com/google/devtools/mobileharness/infra/master/rpc/stub/grpc:lab_sync", + "//src/java/com/google/devtools/mobileharness/service/deviceconfig/rpc/stub:annotation", + "//src/java/com/google/devtools/mobileharness/service/deviceconfig/rpc/stub:device_config_stub", "//src/java/com/google/devtools/mobileharness/shared/constant:log_record_importance", "//src/java/com/google/devtools/mobileharness/shared/constant/hostmanagement:host_property_constants", "//src/java/com/google/devtools/mobileharness/shared/file/resolver:abstract_file_resolver", diff --git a/src/java/com/google/devtools/mobileharness/infra/lab/LabServerModule.java b/src/java/com/google/devtools/mobileharness/infra/lab/LabServerModule.java index f4ba175f87..ca6ccaccf1 100644 --- a/src/java/com/google/devtools/mobileharness/infra/lab/LabServerModule.java +++ b/src/java/com/google/devtools/mobileharness/infra/lab/LabServerModule.java @@ -31,10 +31,14 @@ import com.google.devtools.mobileharness.infra.controller.device.bootstrap.DetectorsAndDispatchers; import com.google.devtools.mobileharness.infra.controller.device.external.ExternalDeviceManager; import com.google.devtools.mobileharness.infra.controller.device.external.NoopExternalDeviceManager; +import com.google.devtools.mobileharness.infra.controller.device.provider.AllocatedDeviceProvisioningModule; +import com.google.devtools.mobileharness.infra.controller.device.provider.LocalDeviceProvisioningModule; import com.google.devtools.mobileharness.infra.controller.messaging.MessageSenderFinder; import com.google.devtools.mobileharness.infra.controller.messaging.MessagingManager; import com.google.devtools.mobileharness.infra.controller.messaging.MessagingManagerHolder; import com.google.devtools.mobileharness.infra.controller.messaging.MessagingServiceModule; +import com.google.devtools.mobileharness.infra.controller.test.launcher.LocalDeviceLauncherProvisioningModule; +import com.google.devtools.mobileharness.infra.controller.test.launcher.ThreadPoolLauncherProvisioningModule; import com.google.devtools.mobileharness.infra.controller.test.manager.LabDirectTestRunnerUtil; import com.google.devtools.mobileharness.infra.controller.test.manager.ProxyTestManager; import com.google.devtools.mobileharness.infra.controller.test.manager.TestManager; @@ -52,6 +56,7 @@ import com.google.devtools.mobileharness.shared.file.resolver.LocalFileResolver; import com.google.devtools.mobileharness.shared.util.concurrent.ServiceModule; import com.google.devtools.mobileharness.shared.util.file.local.LocalFileUtil; +import com.google.devtools.mobileharness.shared.util.flags.Flags; import com.google.devtools.mobileharness.shared.util.system.SystemUtil; import com.google.inject.AbstractModule; import com.google.inject.Key; @@ -92,6 +97,13 @@ protected void configure() { bind(new Key>() {}).to(ProxyTestManager.class); bind(LabDirectTestRunnerHolder.class).to(ProxyTestManager.class); bind(EventBus.class).annotatedWith(GlobalEventBus.class).toInstance(globalInternalBus); + if (Flags.instance().enableDeviceTestDecoupling.get()) { + install(new AllocatedDeviceProvisioningModule()); + install(new ThreadPoolLauncherProvisioningModule()); + } else { + install(new LocalDeviceProvisioningModule()); + install(new LocalDeviceLauncherProvisioningModule()); + } Multibinder subscriberBinder = Multibinder.newSetBinder(binder(), Key.get(Object.class, GlobalEventBusSubscriber.class)); diff --git a/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/BUILD b/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/BUILD index a3c2264eca..40cc82a040 100644 --- a/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/BUILD +++ b/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/BUILD @@ -39,7 +39,6 @@ java_library( name = "prepare_test", srcs = ["PrepareTestServiceImpl.java"], deps = [ - "//src/devtools/mobileharness/api/model/proto:job_java_proto", "//src/devtools/mobileharness/infra/container/proto:mode_setting_java_proto", "//src/devtools/mobileharness/infra/container/proto:test_engine_java_proto", "//src/devtools/mobileharness/infra/lab/proto:prepare_test_service_java_proto", @@ -53,10 +52,9 @@ java_library( "//src/java/com/google/devtools/mobileharness/api/model/lab:locator", "//src/java/com/google/devtools/mobileharness/infra/container/controller:proxy_test_runner", "//src/java/com/google/devtools/mobileharness/infra/container/controller:proxy_to_direct_test_runner", - "//src/java/com/google/devtools/mobileharness/infra/controller/device:test_executor", - "//src/java/com/google/devtools/mobileharness/infra/controller/device:test_executor_provider", + "//src/java/com/google/devtools/mobileharness/infra/controller/device/provider:device_provider", "//src/java/com/google/devtools/mobileharness/infra/controller/test:abstract_test_runner", - "//src/java/com/google/devtools/mobileharness/infra/controller/test/launcher:local_device_test_runner_launcher", + "//src/java/com/google/devtools/mobileharness/infra/controller/test/launcher:launcher_provider", "//src/java/com/google/devtools/mobileharness/infra/controller/test/manager:proxy_test_manager", "//src/java/com/google/devtools/mobileharness/infra/controller/test/model:test_execution_unit", "//src/java/com/google/devtools/mobileharness/infra/lab:annotations", @@ -77,7 +75,6 @@ java_library( "//src/java/com/google/devtools/mobileharness/shared/version", "//src/java/com/google/devtools/mobileharness/shared/version/checker", "//src/java/com/google/wireless/qa/mobileharness/shared/api", - "//src/java/com/google/wireless/qa/mobileharness/shared/proto:job_java_proto", "//src/java/com/google/wireless/qa/mobileharness/shared/util:base", "//src/java/com/google/wireless/qa/mobileharness/shared/util:device", "//src/java/com/google/wireless/qa/mobileharness/shared/util:net_util", @@ -99,6 +96,7 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/controller/test:direct_test_runner", "//src/java/com/google/devtools/mobileharness/infra/controller/test:direct_test_runner_setting", "//src/java/com/google/devtools/mobileharness/infra/controller/test/exception", + "//src/java/com/google/devtools/mobileharness/infra/controller/test/manager:proxy_test_manager", "//src/java/com/google/devtools/mobileharness/infra/lab/common/env", "//src/java/com/google/devtools/mobileharness/infra/lab/controller:file_publisher", "//src/java/com/google/devtools/mobileharness/infra/lab/controller:forwarding_test_message_buffer", @@ -109,6 +107,7 @@ java_library( "//src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/util:test_info_creator", "//src/java/com/google/devtools/mobileharness/shared/util/comm/messaging/message", "//src/java/com/google/devtools/mobileharness/shared/util/file/local", + "//src/java/com/google/devtools/mobileharness/shared/util/flags", "//src/java/com/google/devtools/mobileharness/shared/util/logging:google_logger", "//src/java/com/google/devtools/mobileharness/shared/util/message:str_pair", "//src/java/com/google/wireless/qa/mobileharness/lab/proto:exec_test_serv_java_proto", diff --git a/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/ExecTestServiceImpl.java b/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/ExecTestServiceImpl.java index f0b859c68e..d6fa378b01 100644 --- a/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/ExecTestServiceImpl.java +++ b/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/ExecTestServiceImpl.java @@ -33,6 +33,7 @@ import com.google.devtools.mobileharness.infra.controller.test.DirectTestRunnerSetting; import com.google.devtools.mobileharness.infra.controller.test.TestRunnerLauncher; import com.google.devtools.mobileharness.infra.controller.test.exception.TestRunnerLauncherConnectedException; +import com.google.devtools.mobileharness.infra.controller.test.manager.ProxyTestManager; import com.google.devtools.mobileharness.infra.lab.common.env.UtrsEnvironments; import com.google.devtools.mobileharness.infra.lab.controller.FilePublisher; import com.google.devtools.mobileharness.infra.lab.controller.ForwardingTestMessageBuffer; @@ -43,6 +44,7 @@ import com.google.devtools.mobileharness.infra.lab.rpc.service.util.TestInfoCreator; import com.google.devtools.mobileharness.shared.util.comm.messaging.message.TestMessageInfo; import com.google.devtools.mobileharness.shared.util.file.local.LocalFileUtil; +import com.google.devtools.mobileharness.shared.util.flags.Flags; import com.google.devtools.mobileharness.shared.util.message.StrPairUtil; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.inject.assistedinject.Assisted; @@ -70,7 +72,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import javax.annotation.Nullable; import javax.inject.Inject; @@ -86,7 +87,6 @@ public interface ExecTestServiceImplFactory { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private final LabDirectTestRunnerHolder testRunnerHolder; - private final DeviceHelperFactory deviceHelperFactory; private final LabResponseProtoGenerator labResponseProtoGenerator; @@ -177,10 +177,20 @@ public KickOffTestResponse kickOffTest(KickOffTestRequest req) throws MobileHarn e); } - // Gets DeviceHelpers. - List devices = new ArrayList<>(); - for (String deviceId : req.getDeviceIdList()) { - devices.add(deviceHelperFactory.getDeviceHelper(deviceId)); + List devices; + if (Flags.instance().enableDeviceTestDecoupling.get()) { + if (!(testRunnerHolder instanceof ProxyTestManager proxyTestManager)) { + throw new MobileHarnessException( + InfraErrorId.LAB_RPC_EXEC_TEST_DECOUPLING_NOT_SUPPORTED, + "Device decoupling is not supported in this environment."); + } + devices = + proxyTestManager.getProxyToDirectTestRunner(testInfo.locator().getId()).getDevices(); + } else { + devices = new ArrayList<>(); + for (String deviceId : req.getDeviceIdList()) { + devices.add(deviceHelperFactory.getDeviceHelper(deviceId)); + } } List deviceIds = devices.stream().map(Device::getDeviceId).collect(toImmutableList()); @@ -194,7 +204,7 @@ public KickOffTestResponse kickOffTest(KickOffTestRequest req) throws MobileHarn devices.stream() .map(Device::getDimensions) .map(StrPairUtil::convertCollectionToMultimap) - .collect(Collectors.toList())); + .collect(toImmutableList())); // Creates DirectTestRunner. TestRunnerLauncher connectorTestRunnerLauncher = diff --git a/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/PrepareTestServiceImpl.java b/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/PrepareTestServiceImpl.java index b1a7bf8bd2..f9b2298b58 100644 --- a/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/PrepareTestServiceImpl.java +++ b/src/java/com/google/devtools/mobileharness/infra/lab/rpc/service/PrepareTestServiceImpl.java @@ -27,9 +27,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.google.common.eventbus.EventBus; import com.google.common.flogger.FluentLogger; import com.google.common.util.concurrent.Futures; @@ -39,7 +36,6 @@ import com.google.devtools.mobileharness.api.model.error.BasicErrorId; import com.google.devtools.mobileharness.api.model.error.InfraErrorId; import com.google.devtools.mobileharness.api.model.error.MobileHarnessException; -import com.google.devtools.mobileharness.api.model.error.MobileHarnessExceptions; import com.google.devtools.mobileharness.api.model.job.JobLocator; import com.google.devtools.mobileharness.api.model.job.TestLocator; import com.google.devtools.mobileharness.api.model.job.in.Dirs; @@ -47,7 +43,6 @@ import com.google.devtools.mobileharness.api.model.job.out.Timing; import com.google.devtools.mobileharness.api.model.lab.DeviceLocator; import com.google.devtools.mobileharness.api.model.lab.LabLocator; -import com.google.devtools.mobileharness.api.model.proto.Job.JobFeature; import com.google.devtools.mobileharness.infra.container.controller.ProxyTestRunner; import com.google.devtools.mobileharness.infra.container.controller.ProxyToDirectTestRunner; import com.google.devtools.mobileharness.infra.container.proto.TestEngine.ResolveFileStatus; @@ -55,10 +50,9 @@ import com.google.devtools.mobileharness.infra.container.proto.TestEngine.TestEngineLocator.GrpcLocator; import com.google.devtools.mobileharness.infra.container.proto.TestEngine.TestEngineLocator.StubbyLocator; import com.google.devtools.mobileharness.infra.container.proto.TestEngine.TestEngineStatus; -import com.google.devtools.mobileharness.infra.controller.device.TestExecutor; -import com.google.devtools.mobileharness.infra.controller.device.TestExecutorProvider; +import com.google.devtools.mobileharness.infra.controller.device.provider.DeviceProvider; import com.google.devtools.mobileharness.infra.controller.test.TestRunnerLauncher; -import com.google.devtools.mobileharness.infra.controller.test.launcher.LocalDeviceTestRunnerLauncher; +import com.google.devtools.mobileharness.infra.controller.test.launcher.LauncherProvider; import com.google.devtools.mobileharness.infra.controller.test.manager.ProxyTestManager; import com.google.devtools.mobileharness.infra.controller.test.manager.TestStartedException; import com.google.devtools.mobileharness.infra.controller.test.model.JobExecutionUnit; @@ -92,18 +86,15 @@ import com.google.devtools.mobileharness.shared.util.file.local.ResUtil; import com.google.devtools.mobileharness.shared.util.path.PathUtil; import com.google.devtools.mobileharness.shared.util.system.SystemUtil; -import com.google.devtools.mobileharness.shared.util.time.Sleeper; import com.google.devtools.mobileharness.shared.version.Version; import com.google.devtools.mobileharness.shared.version.checker.ServiceSideVersionChecker; import com.google.devtools.mobileharness.shared.version.proto.VersionProto.VersionCheckResponse; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.wireless.qa.mobileharness.shared.api.device.Device; -import com.google.wireless.qa.mobileharness.shared.proto.Job.JobType; import com.google.wireless.qa.mobileharness.shared.util.NetUtil; import java.time.Clock; import java.time.Duration; import java.time.Instant; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; @@ -120,9 +111,6 @@ public class PrepareTestServiceImpl { private static final String SATELLITE_LAB_TEST_ENGINE_RESOURCE_PATH = "/com/google/devtools/mobileharness/infra/container/testengine/SatelliteLabTestEngine_deploy.jar"; - private static final Duration WAIT_DEVICE_READY_TIMEOUT = Duration.ofSeconds(20L); - - private final TestExecutorProvider testExecutorProvider; private final JobManager jobManager; private final ProxyTestManager testManager; private final ServiceSideVersionChecker versionChecker = @@ -140,9 +128,11 @@ public class PrepareTestServiceImpl { private final EventBus globalInternalEventBus; private final FileResolver fileResolver; + private final DeviceProvider deviceProvider; + private final LauncherProvider launcherProvider; + @Inject public PrepareTestServiceImpl( - TestExecutorProvider testExecutorProvider, JobManager jobManager, ProxyTestManager testManager, LocalFileUtil localFileUtil, @@ -155,8 +145,9 @@ public PrepareTestServiceImpl( @ServViaCloudRpc boolean servViaCloudRpc, @CloudRpcDnsAddress String cloudRpcDnsName, @CloudRpcShardName String cloudRpcShardName, + DeviceProvider deviceProvider, + LauncherProvider launcherProvider, @GlobalEventBus EventBus globalInternalEventBus) { - this.testExecutorProvider = testExecutorProvider; this.jobManager = jobManager; this.testManager = testManager; this.localFileUtil = localFileUtil; @@ -170,6 +161,8 @@ public PrepareTestServiceImpl( this.cloudRpcShardName = cloudRpcShardName; this.globalInternalEventBus = globalInternalEventBus; this.fileResolver = fileResolver; + this.deviceProvider = deviceProvider; + this.launcherProvider = launcherProvider; } @CanIgnoreReturnValue @@ -181,12 +174,6 @@ public CreateTestResponse createTest(CreateTestRequest req) VersionCheckResponse versionCheckResponse = versionChecker.checkStub(req.getVersionCheckRequest()); - // Gets TestExecutors. - List testExecutors = getTestExecutorsUntilReady(req.getDeviceIdList()); - - // Checks the job feature. - checkJobFeature(req.getJob().getJobFeature(), testExecutors); - // Creates JobExecutionUnit if absent. JobExecutionUnit jobExecutionUnit = createAndAddJobIfAbsent(req.getJob()); @@ -194,12 +181,12 @@ public CreateTestResponse createTest(CreateTestRequest req) TestExecutionUnit testExecutionUnit = createTestExecutionUnit(req.getTest(), jobExecutionUnit); ImmutableList devices = - testExecutors.stream().map(TestExecutor::getDevice).collect(toImmutableList()); + deviceProvider.getDevices(req.getDeviceIdList(), req.getAllocatedDevicesList()); // Creates TestRunnerLauncher. TestRunnerLauncher launcher = - new LocalDeviceTestRunnerLauncher( - testExecutors.get(0), testExecutors.stream().skip(1L).collect(toImmutableList())); + launcherProvider.getLauncher( + testExecutionUnit.locator().id(), req.getJob().getJobFeature(), devices); // Creates Allocation. Allocation allocation = @@ -257,11 +244,7 @@ public CreateTestResponse createTest(CreateTestRequest req) CreateTestResponse response = CreateTestResponse.newBuilder() .setVersionCheckResponse(versionCheckResponse) - .addAllDeviceFeature( - testExecutors.stream() - .map(TestExecutor::getDevice) - .map(Device::toFeature) - .collect(toImmutableList())) + .addAllDeviceFeature(devices.stream().map(Device::toFeature).collect(toImmutableList())) .setContainerInfo( ContainerInfo.newBuilder() .setIsContainerMode(proxyTestRunner.isContainerMode()) @@ -363,58 +346,6 @@ private TestRunnerTiming getTestTiming(String testId) throws MobileHarnessExcept return testRunnerTiming.build(); } - private void checkJobFeature(JobFeature jobFeature, List testExecutors) - throws MobileHarnessException { - // TODO: Checks device requirement directly rather than job type. - JobType primaryDeviceJobType = - JobType.newBuilder() - .setDriver(jobFeature.getDriver()) - .setDevice(jobFeature.getDeviceRequirements().getDeviceRequirement(0).getDeviceType()) - .addAllDecorator( - Lists.reverse( - jobFeature.getDeviceRequirements().getDeviceRequirement(0).getDecoratorList())) - .build(); - - for (TestExecutor testExecutor : testExecutors) { - if (isJobSupported(testExecutor.getDevice(), primaryDeviceJobType)) { - return; - } - } - - throw new MobileHarnessException( - InfraErrorId.LAB_RPC_PREPARE_TEST_JOB_TYPE_NOT_SUPPORTED, - String.format("Job type [%s] is not supported by MH lab", primaryDeviceJobType)); - } - - /** Checks whether the job type is supported by this device. */ - private static boolean isJobSupported(Device device, JobType jobType) { - if (!device.getDeviceTypes().contains(jobType.getDevice())) { - logger.atWarning().log( - "The device type [%s] is not supported by the device with ID %s", - Sets.difference(ImmutableSet.of(jobType.getDevice()), device.getDeviceTypes()), - device.getDeviceControlId()); - return false; - } - - if (!device.getDriverTypes().contains(jobType.getDriver())) { - logger.atWarning().log( - "The driver [%s] is not supported by the device with ID %s", - Sets.difference(ImmutableSet.of(jobType.getDriver()), device.getDriverTypes()), - device.getDeviceControlId()); - return false; - } - - if (!device.getDecoratorTypes().containsAll(jobType.getDecoratorList())) { - logger.atWarning().log( - "The decorators [%s] are not supported by the device with ID %s", - Sets.difference( - ImmutableSet.copyOf(jobType.getDecoratorList()), device.getDecoratorTypes()), - device.getDeviceControlId()); - return false; - } - return true; - } - private JobExecutionUnit createAndAddJobIfAbsent(CreateTestRequest.Job job) { String jobId = job.getJobId(); JobLocator jobLocator = JobLocator.of(jobId, job.getJobName()); @@ -446,48 +377,6 @@ private TestExecutionUnit createTestExecutionUnit( return new TestExecutionUnit(testLocator, testTiming, job); } - private List getTestExecutorsUntilReady(List deviceIds) - throws MobileHarnessException, InterruptedException { - // Waits for the device to be ready, since the device maybe INIT in LabServer. - Clock clock = Clock.systemUTC(); - Instant expireTime = clock.instant().plus(WAIT_DEVICE_READY_TIMEOUT); - Sleeper sleeper = Sleeper.defaultSleeper(); - int attempts = 0; - while (true) { - try { - return getTestExecutors(deviceIds); - } catch (MobileHarnessException e) { - if (clock.instant().isAfter(expireTime) - || (e.getErrorId() != InfraErrorId.LAB_RPC_PREPARE_TEST_DEVICE_NOT_ALIVE - && e.getErrorId() != InfraErrorId.LAB_RPC_PREPARE_TEST_DEVICE_NOT_FOUND)) { - throw e; - } - logger.atWarning().log( - "%d failed attempts to get device runners of %s, try again later", - ++attempts, deviceIds); - sleeper.sleep(Duration.ofSeconds(1)); - } - } - } - - private List getTestExecutors(List deviceIds) - throws MobileHarnessException { - List testExecutors = new ArrayList<>(); - for (String deviceId : deviceIds) { - TestExecutor testExecutor = testExecutorProvider.getTestExecutorForDeviceId(deviceId); - MobileHarnessExceptions.check( - testExecutor != null, - InfraErrorId.LAB_RPC_PREPARE_TEST_DEVICE_NOT_FOUND, - () -> String.format("Device [%s] does not exist", deviceId)); - MobileHarnessExceptions.check( - testExecutor.isAlive(), - InfraErrorId.LAB_RPC_PREPARE_TEST_DEVICE_NOT_ALIVE, - () -> String.format("Device [%s] is not alive when preparing test", deviceId)); - testExecutors.add(testExecutor); - } - return testExecutors; - } - private ProxyTestRunner createTestRunner( ContainerSetting containerSetting, TestRunnerLauncher launcher, @@ -500,6 +389,7 @@ private ProxyTestRunner createTestRunner( launcher, testExecutionUnit, allocation, + devices, new LabFileNotifier(), getProxiedTestEngineLocator()); } diff --git a/src/java/com/google/devtools/mobileharness/shared/util/flags/Flags.java b/src/java/com/google/devtools/mobileharness/shared/util/flags/Flags.java index 000e22fe05..ab79d63285 100644 --- a/src/java/com/google/devtools/mobileharness/shared/util/flags/Flags.java +++ b/src/java/com/google/devtools/mobileharness/shared/util/flags/Flags.java @@ -1068,6 +1068,14 @@ public enum ConfigServiceStorageType { converter = Flag.BooleanConverter.class) public Flag enableDeviceSystemSettingsChange = enableDeviceSystemSettingsChangeDefault; + private static final Flag enableDeviceTestDecouplingDefault = Flag.value(false); + + @com.beust.jcommander.Parameter( + names = "--enable_device_test_decoupling", + description = "Whether to enable device/test decoupling mode. Default is false.", + converter = Flag.BooleanConverter.class) + public Flag enableDeviceTestDecoupling = enableDeviceTestDecouplingDefault; + private static final Flag enableDiskCheckDefault = Flag.value(true); @com.beust.jcommander.Parameter( diff --git a/src/javatests/com/google/devtools/mobileharness/shared/size/BinarySizeTest.java b/src/javatests/com/google/devtools/mobileharness/shared/size/BinarySizeTest.java index 1f34a69057..659ecb9ecb 100644 --- a/src/javatests/com/google/devtools/mobileharness/shared/size/BinarySizeTest.java +++ b/src/javatests/com/google/devtools/mobileharness/shared/size/BinarySizeTest.java @@ -59,7 +59,7 @@ public class BinarySizeTest { "ats_olc_server_local_mode", 41_950_000L, "lab_server", - 42_250_000L, + 43_250_000L, "ats_console", 22_550_000L, "persistent_cache_manager",