Java tutorial
/* * Copyright (C) 2016 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.build.gradle.integration.instant; import static com.android.build.gradle.integration.common.truth.TruthHelper.assertThat; import static com.android.build.gradle.integration.common.utils.DeviceHelper.DEFAULT_ADB_TIMEOUT_MSEC; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.Assert.assertNotNull; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.build.gradle.integration.common.fixture.GradleTestProject; import com.android.build.gradle.integration.common.fixture.Packaging; import com.android.build.gradle.internal.incremental.ColdswapMode; import com.android.build.gradle.internal.incremental.InstantRunBuildContext; import com.android.builder.model.AndroidProject; import com.android.builder.model.InstantRun; import com.android.builder.model.OptionalCompilationStep; import com.android.builder.model.Variant; import com.android.builder.testing.api.DeviceException; import com.android.ddmlib.CollectingOutputReceiver; import com.android.ddmlib.IDevice; import com.android.ddmlib.IShellOutputReceiver; import com.android.ddmlib.InstallException; import com.android.tools.fd.client.AppState; import com.android.tools.fd.client.InstantRunArtifact; import com.android.tools.fd.client.InstantRunArtifactType; import com.android.tools.fd.client.InstantRunBuildInfo; import com.android.tools.fd.client.InstantRunClient; import com.google.common.base.Charsets; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.io.Files; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.EnumSet; import java.util.List; import java.util.concurrent.TimeUnit; public final class InstantRunTestUtils { private static final int SLEEP_TIME_MSEC = 200; @NonNull public static InstantRunBuildInfo loadContext(@NonNull InstantRun instantRunModel) throws Exception { InstantRunBuildInfo context = InstantRunBuildInfo .get(Files.toString(instantRunModel.getInfoFile(), Charsets.UTF_8)); assertNotNull(context); return context; } @NonNull public static InstantRunBuildContext loadBuildContext(int apiLevel, @NonNull InstantRun instantRunModel) throws Exception { InstantRunBuildContext context = new InstantRunBuildContext(); context.setApiLevel(apiLevel, null, null); context.loadFromXml(Files.toString(instantRunModel.getInfoFile(), Charsets.UTF_8)); return context; } @NonNull public static InstantRun getInstantRunModel(@NonNull AndroidProject project) { Collection<Variant> variants = project.getVariants(); for (Variant variant : variants) { if ("debug".equals(variant.getName())) { return variant.getMainArtifact().getInstantRun(); } } throw new AssertionError("Could not find debug variant."); } static void doInstall(@NonNull IDevice device, @NonNull List<InstantRunArtifact> artifacts) throws DeviceException, InstallException { List<File> apkFiles = Lists.newArrayList(); for (InstantRunArtifact artifact : artifacts) { if (artifact.type == InstantRunArtifactType.SPLIT) { apkFiles.add(artifact.file); } if (artifact.type == InstantRunArtifactType.MAIN || artifact.type == InstantRunArtifactType.SPLIT_MAIN) { apkFiles.add(0, artifact.file); } } if (device.getVersion().isGreaterOrEqualThan(21)) { device.installPackages(apkFiles, true /*reinstall*/, ImmutableList.<String>of(), DEFAULT_ADB_TIMEOUT_MSEC, MILLISECONDS); } else { assertThat(apkFiles).hasSize(1); device.installPackage(Iterables.getOnlyElement(apkFiles).getAbsolutePath(), true /*reinstall*/); } } static void runApp(IDevice device, String target) throws Exception { IShellOutputReceiver receiver = new CollectingOutputReceiver(); String command = "am start" + " -n " + target + " -a android.intent.action.MAIN" + " -c android.intent.category.LAUNCHER"; device.executeShellCommand(command, receiver, DEFAULT_ADB_TIMEOUT_MSEC, MILLISECONDS); } static void stopApp(@NonNull IDevice device, @NonNull String target) throws Exception { IShellOutputReceiver receiver = new CollectingOutputReceiver(); String command = "am start" + " -n " + target + " -a android.intent.action.MAIN" + " -c android.intent.category.LAUNCHER"; device.executeShellCommand(command, receiver, DEFAULT_ADB_TIMEOUT_MSEC, MILLISECONDS); } static void unlockDevice(@NonNull IDevice device) throws Exception { IShellOutputReceiver receiver = new CollectingOutputReceiver(); device.executeShellCommand("input keyevent KEYCODE_WAKEUP", receiver, DEFAULT_ADB_TIMEOUT_MSEC, MILLISECONDS); device.executeShellCommand("wm dismiss-keyguard", receiver, DEFAULT_ADB_TIMEOUT_MSEC, MILLISECONDS); } @NonNull static InstantRun doInitialBuild(@NonNull GradleTestProject project, @NonNull Packaging packaging, int apiLevel, @NonNull ColdswapMode coldswapMode) { project.execute("clean"); InstantRun instantRunModel = getInstantRunModel(project.model().getSingle()); project.executor().withInstantRun(apiLevel, coldswapMode, OptionalCompilationStep.FULL_APK) .withPackaging(packaging).run("assembleDebug"); return instantRunModel; } @NonNull public static InstantRunArtifact getOnlyArtifact(@NonNull InstantRun instantRunModel) throws Exception { InstantRunBuildInfo context = loadContext(instantRunModel); assertThat(context.getArtifacts()).hasSize(1); return Iterables.getOnlyElement(context.getArtifacts()); } /** * Gets the RELOAD_DEX {@link InstantRunArtifact} produced by last build. */ @NonNull public static InstantRunArtifact getReloadDexArtifact(@NonNull InstantRun instantRunModel) throws Exception { InstantRunArtifact artifact = getOnlyArtifact(instantRunModel); assertThat(artifact.type).isEqualTo(InstantRunArtifactType.RELOAD_DEX); return artifact; } /** * Gets the RESOURCES {@link InstantRunArtifact} produced by last build. */ @NonNull public static InstantRunArtifact getResourcesArtifact(@NonNull InstantRun instantRunModel) throws Exception { InstantRunArtifact artifact = getOnlyArtifact(instantRunModel); assertThat(artifact.type).isEqualTo(InstantRunArtifactType.RESOURCES); return artifact; } @NonNull public static List<InstantRunArtifact> getCompiledColdSwapChange(@NonNull InstantRun instantRunModel, @NonNull ColdswapMode coldswapMode) throws Exception { List<InstantRunArtifact> artifacts = loadContext(instantRunModel).getArtifacts(); assertThat(artifacts).isNotEmpty(); EnumSet<InstantRunArtifactType> allowedArtifactTypes; switch (coldswapMode) { case MULTIAPK: allowedArtifactTypes = EnumSet.of(InstantRunArtifactType.SPLIT, InstantRunArtifactType.SPLIT_MAIN); break; case MULTIDEX: allowedArtifactTypes = EnumSet.of(InstantRunArtifactType.DEX); break; default: throw new IllegalArgumentException("Expecting cold swap mode to be explicitly specified"); } for (InstantRunArtifact artifact : artifacts) { if (!allowedArtifactTypes.contains(artifact.type)) { throw new AssertionError("Unexpected artifact " + artifact); } } return artifacts; } public static void printBuildInfoFile(@Nullable InstantRun instantRunModel) { if (instantRunModel == null) { System.err.println("Cannot print build info file as model is null"); return; } try { System.out.println("------------ build info file ------------\n" + Files.toString(instantRunModel.getInfoFile(), Charsets.UTF_8) + "---------- end build info file ----------\n"); } catch (IOException e) { System.err.println("Unable to print build info xml file: \n" + Throwables.getStackTraceAsString(e)); } } static void waitForAppStart(@NonNull InstantRunClient client, @NonNull IDevice device) throws InterruptedException, IOException { AppState appState = null; int times = 0; while (appState != AppState.FOREGROUND) { if (times > TimeUnit.SECONDS.toMillis(15)) { throw new AssertionError("App did not start"); } Thread.sleep(SLEEP_TIME_MSEC); times += SLEEP_TIME_MSEC; try { appState = client.getAppState(device); } catch (IOException e) { System.err.println(Throwables.getStackTraceAsString(e)); } } } }