aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-01-12 17:49:55 -0800
committerAndroid Code Review <code-review@android.com>2011-01-12 17:49:55 -0800
commit6fb212b55eb3c2819c7a4f530f6beb3586b0a07e (patch)
tree648f78e7c047a4859ff63cb89fe6e08b6d359e7f
parentf4df12efd1906b947b32e92489b241ac19fab2e6 (diff)
parent57aa211a4bff699d81f755c0d827b496ad7eef26 (diff)
downloadsdk-6fb212b55eb3c2819c7a4f530f6beb3586b0a07e.zip
sdk-6fb212b55eb3c2819c7a4f530f6beb3586b0a07e.tar.gz
sdk-6fb212b55eb3c2819c7a4f530f6beb3586b0a07e.tar.bz2
Merge "Merge 74f725db from master: Add snapshot handling for AVD creation, details, and launch" into tools_r9
-rw-r--r--androidprefs/src/com/android/prefs/AndroidLocation.java7
-rw-r--r--build/tools.atree1
-rw-r--r--emulator/snapshot/snapshots.imgbin0 -> 262144 bytes
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java1
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/Main.java132
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java9
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java90
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/MainTest.java100
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/MockLog.java57
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/SdkCommandLineTest.java36
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java88
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java7
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java78
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java30
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java5
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java10
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java81
17 files changed, 651 insertions, 81 deletions
diff --git a/androidprefs/src/com/android/prefs/AndroidLocation.java b/androidprefs/src/com/android/prefs/AndroidLocation.java
index 9a537d5..c36048a 100644
--- a/androidprefs/src/com/android/prefs/AndroidLocation.java
+++ b/androidprefs/src/com/android/prefs/AndroidLocation.java
@@ -82,6 +82,13 @@ public final class AndroidLocation {
}
/**
+ * Resets the folder used to store android related files. For testing.
+ */
+ public final static void resetFolder() {
+ sPrefsLocation = null;
+ }
+
+ /**
* Checks a list of system properties and/or system environment variables for validity, and
* existing director, and returns the first one.
* @param names
diff --git a/build/tools.atree b/build/tools.atree
index 140a35e..c28f044 100644
--- a/build/tools.atree
+++ b/build/tools.atree
@@ -41,6 +41,7 @@ bin/zipalign tools/zipalign
# emulator
bin/emulator tools/emulator
+sdk/emulator/snapshot/snapshots.img tools/lib/emulator/snapshots.img
# Java-Based SDK Tools
bin/ddms tools/ddms
diff --git a/emulator/snapshot/snapshots.img b/emulator/snapshot/snapshots.img
new file mode 100644
index 0000000..c05bbda
--- /dev/null
+++ b/emulator/snapshot/snapshots.img
Binary files differ
diff --git a/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java b/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java
index 73b0f6b..8f5dec4 100644
--- a/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java
+++ b/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java
@@ -828,6 +828,7 @@ class CommandLineProcessor {
* Internal helper to define a new argument for a give action.
*
* @param mode The {@link Mode} for the argument.
+ * @param mandatory The argument is required (never if {@link Mode.BOOLEAN})
* @param verb The verb name. Can be #INTERNAL_VERB.
* @param directObject The action name. Can be #NO_VERB_OBJECT or #INTERNAL_FLAG.
* @param shortName The one-letter short argument name. Can be empty but not null.
diff --git a/sdkmanager/app/src/com/android/sdkmanager/Main.java b/sdkmanager/app/src/com/android/sdkmanager/Main.java
index e951cc5..1fe6d97 100644
--- a/sdkmanager/app/src/com/android/sdkmanager/Main.java
+++ b/sdkmanager/app/src/com/android/sdkmanager/Main.java
@@ -19,17 +19,17 @@ package com.android.sdkmanager;
import com.android.prefs.AndroidLocation;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
-import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.avd.HardwareProperties;
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
+import com.android.sdklib.internal.avd.HardwareProperties;
import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.internal.project.ProjectCreator;
-import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdklib.internal.project.ProjectCreator.OutputLevel;
+import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
import com.android.sdklib.io.FileWrapper;
import com.android.sdklib.repository.SdkRepoConstants;
@@ -133,6 +133,11 @@ public class Main {
};
}
+ /** For testing */
+ public void setLogger(ISdkLog logger) {
+ mSdkLog = logger;
+ }
+
/**
* Init the application by making sure the SDK path is available and
* doing basic parsing of the SDK.
@@ -788,72 +793,84 @@ public class Main {
}
/**
- * Displays the list of available AVDs.
+ * Displays the list of available AVDs for the given AvdManager.
+ *
+ * @param avdManager
*/
- private void displayAvdList() {
- try {
- AvdManager avdManager = new AvdManager(mSdkManager, mSdkLog);
+ public void displayAvdList(AvdManager avdManager) {
+ mSdkLog.printf("Available Android Virtual Devices:\n");
+
+ AvdInfo[] avds = avdManager.getValidAvds();
+ for (int index = 0 ; index < avds.length ; index++) {
+ AvdInfo info = avds[index];
+ if (index > 0) {
+ mSdkLog.printf("---------\n");
+ }
+ mSdkLog.printf(" Name: %s\n", info.getName());
+ mSdkLog.printf(" Path: %s\n", info.getPath());
- mSdkLog.printf("Available Android Virtual Devices:\n");
+ // get the target of the AVD
+ IAndroidTarget target = info.getTarget();
+ if (target.isPlatform()) {
+ mSdkLog.printf(" Target: %s (API level %s)\n", target.getName(),
+ target.getVersion().getApiString());
+ } else {
+ mSdkLog.printf(" Target: %s (%s)\n", target.getName(), target
+ .getVendor());
+ mSdkLog.printf(" Based on Android %s (API level %s)\n",
+ target.getVersionName(), target.getVersion().getApiString());
+ }
- AvdInfo[] avds = avdManager.getValidAvds();
- for (int index = 0 ; index < avds.length ; index++) {
- AvdInfo info = avds[index];
- if (index > 0) {
- mSdkLog.printf("---------\n");
+ // display some extra values.
+ Map<String, String> properties = info.getProperties();
+ if (properties != null) {
+ String skin = properties.get(AvdManager.AVD_INI_SKIN_NAME);
+ if (skin != null) {
+ mSdkLog.printf(" Skin: %s\n", skin);
}
- mSdkLog.printf(" Name: %s\n", info.getName());
- mSdkLog.printf(" Path: %s\n", info.getPath());
-
- // get the target of the AVD
- IAndroidTarget target = info.getTarget();
- if (target.isPlatform()) {
- mSdkLog.printf(" Target: %s (API level %s)\n", target.getName(),
- target.getVersion().getApiString());
- } else {
- mSdkLog.printf(" Target: %s (%s)\n", target.getName(), target
- .getVendor());
- mSdkLog.printf(" Based on Android %s (API level %s)\n",
- target.getVersionName(), target.getVersion().getApiString());
+ String sdcard = properties.get(AvdManager.AVD_INI_SDCARD_SIZE);
+ if (sdcard == null) {
+ sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH);
}
-
- // display some extra values.
- Map<String, String> properties = info.getProperties();
- if (properties != null) {
- String skin = properties.get(AvdManager.AVD_INI_SKIN_NAME);
- if (skin != null) {
- mSdkLog.printf(" Skin: %s\n", skin);
- }
- String sdcard = properties.get(AvdManager.AVD_INI_SDCARD_SIZE);
- if (sdcard == null) {
- sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH);
- }
- if (sdcard != null) {
- mSdkLog.printf(" Sdcard: %s\n", sdcard);
- }
+ if (sdcard != null) {
+ mSdkLog.printf(" Sdcard: %s\n", sdcard);
+ }
+ String snapshot = properties.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
+ if (snapshot != null) {
+ mSdkLog.printf("Snapshot: %s\n", snapshot);
}
}
+ }
- // Are there some unused AVDs?
- AvdInfo[] badAvds = avdManager.getBrokenAvds();
+ // Are there some unused AVDs?
+ AvdInfo[] badAvds = avdManager.getBrokenAvds();
- if (badAvds.length == 0) {
- return;
+ if (badAvds.length == 0) {
+ return;
+ }
+
+ mSdkLog.printf("\nThe following Android Virtual Devices could not be loaded:\n");
+ boolean needSeparator = false;
+ for (AvdInfo info : badAvds) {
+ if (needSeparator) {
+ mSdkLog.printf("---------\n");
}
+ mSdkLog.printf(" Name: %s\n", info.getName() == null ? "--" : info.getName());
+ mSdkLog.printf(" Path: %s\n", info.getPath() == null ? "--" : info.getPath());
- mSdkLog.printf("\nThe following Android Virtual Devices could not be loaded:\n");
- boolean needSeparator = false;
- for (AvdInfo info : badAvds) {
- if (needSeparator) {
- mSdkLog.printf("---------\n");
- }
- mSdkLog.printf(" Name: %s\n", info.getName() == null ? "--" : info.getName());
- mSdkLog.printf(" Path: %s\n", info.getPath() == null ? "--" : info.getPath());
+ String error = info.getErrorMessage();
+ mSdkLog.printf(" Error: %s\n", error == null ? "Uknown error" : error);
+ needSeparator = true;
+ }
+ }
- String error = info.getErrorMessage();
- mSdkLog.printf(" Error: %s\n", error == null ? "Uknown error" : error);
- needSeparator = true;
- }
+ /**
+ * Displays the list of available AVDs.
+ */
+ private void displayAvdList() {
+ try {
+ AvdManager avdManager = new AvdManager(mSdkManager, mSdkLog);
+ displayAvdList(avdManager);
} catch (AndroidLocationException e) {
errorAndExit(e.getMessage());
}
@@ -972,6 +989,7 @@ public class Main {
mSdkCommandLine.getParamSdCard(),
hardwareConfig,
removePrevious,
+ mSdkCommandLine.getFlagSnapshot(),
mSdkLog);
} catch (AndroidLocationException e) {
diff --git a/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java b/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java
index 7062fae..5bb6c4e 100644
--- a/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java
+++ b/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java
@@ -78,6 +78,7 @@ class SdkCommandLine extends CommandLineProcessor {
public static final String KEY_PROXY_HOST = "proxy-host";
public static final String KEY_DRY_MODE = "dry-mode";
public static final String KEY_OBSOLETE = "obsolete";
+ public static final String KEY_SNAPSHOT = "snapshot";
/**
* Action definitions for SdkManager command line.
@@ -166,6 +167,9 @@ class SdkCommandLine extends CommandLineProcessor {
define(Mode.BOOLEAN, false,
VERB_CREATE, OBJECT_AVD, "f", KEY_FORCE,
"Forces creation (overwrites an existing AVD)", false);
+ define(Mode.BOOLEAN, false,
+ VERB_CREATE, OBJECT_AVD, "a", KEY_SNAPSHOT,
+ "Place a snapshots file in the AVD, to enable persistence.", false);
// --- delete avd ---
@@ -408,6 +412,11 @@ class SdkCommandLine extends CommandLineProcessor {
return ((Boolean) getValue(null, null, KEY_FORCE)).booleanValue();
}
+ /** Helper to retrieve the --snapshot flag. */
+ public boolean getFlagSnapshot() {
+ return ((Boolean) getValue(null, null, KEY_SNAPSHOT)).booleanValue();
+ }
+
// -- some helpers for avd action flags
/** Helper to retrieve the --rename value for a move verb. */
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java b/sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java
new file mode 100644
index 0000000..bb1ba75
--- /dev/null
+++ b/sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 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.sdkmanager;
+
+import static java.io.File.createTempFile;
+
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.internal.avd.AvdManager;
+import com.android.sdklib.internal.project.ProjectProperties;
+import com.android.sdklib.io.FileWrapper;
+
+import java.io.File;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+public class AvdManagerTest extends TestCase {
+
+ private AvdManager mAvdManager;
+ private SdkManager mSdkManager;
+ private MockLog mLog;
+ private File mFakeSdk;
+ private File mAvdFolder;
+ private IAndroidTarget mTarget;
+
+ @Override
+ public void setUp() throws Exception {
+ mLog = new MockLog();
+ mFakeSdk = SdkManagerTestUtil.makeFakeSdk(createTempFile(this.getClass().getSimpleName(), null));
+ mSdkManager = SdkManager.createManager(mFakeSdk.getAbsolutePath(), mLog);
+ assertNotNull("sdkManager location was invalid", mSdkManager);
+
+ mAvdManager = new AvdManager(mSdkManager, mLog);
+ mAvdFolder = new File(mFakeSdk, "avdData");
+ mTarget = mSdkManager.getTargets()[0];
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ SdkManagerTestUtil.deleteDir(mFakeSdk);
+ }
+
+ public void testCreateAvdWithoutSnapshot() {
+ mAvdManager.createAvd(
+ mAvdFolder, this.getName(), mTarget, null, null, null, false, false, mLog);
+
+ assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0\n]",
+ mLog.toString());
+ assertTrue("Expected config.ini in " + mAvdFolder,
+ new File(mAvdFolder, "config.ini").exists());
+ Map<String, String> map = ProjectProperties.parsePropertyFile(
+ new FileWrapper(mAvdFolder, "config.ini"), mLog);
+ assertEquals("HVGA", map.get("skin.name"));
+ assertEquals("platforms/v0_0/skins/HVGA", map.get("skin.path"));
+ assertEquals("platforms/v0_0/images/", map.get("image.sysdir.1"));
+ assertEquals(null, map.get("snapshot.present"));
+ assertTrue("Expected userdata.img in " + mAvdFolder,
+ new File(mAvdFolder, "userdata.img").exists());
+ assertFalse("Expected NO snapshots.img in " + mAvdFolder,
+ new File(mAvdFolder, "snapshots.img").exists());
+ }
+
+ public void testCreateAvdWithSnapshot() {
+ mAvdManager.createAvd(
+ mAvdFolder, this.getName(), mTarget, null, null, null, false, true, mLog);
+
+ assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0\n]",
+ mLog.toString());
+ assertTrue("Expected snapshots.img in " + mAvdFolder,
+ new File(mAvdFolder, "snapshots.img").exists());
+ Map<String, String> map = ProjectProperties.parsePropertyFile(
+ new FileWrapper(mAvdFolder, "config.ini"), mLog);
+ assertEquals("true", map.get("snapshot.present"));
+ }
+}
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/MainTest.java b/sdkmanager/app/tests/com/android/sdkmanager/MainTest.java
new file mode 100644
index 0000000..f6e3bbe
--- /dev/null
+++ b/sdkmanager/app/tests/com/android/sdkmanager/MainTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 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.sdkmanager;
+
+
+import static java.io.File.createTempFile;
+
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.internal.avd.AvdManager;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+public class MainTest extends TestCase {
+
+ private File mFakeSdk;
+ private MockLog mLog;
+ private SdkManager mSdkManager;
+ private AvdManager mAvdManager;
+ private File mAvdFolder;
+ private IAndroidTarget mTarget;
+ private File fakeSdkDir;
+
+ @Override
+ public void setUp() throws Exception {
+ mLog = new MockLog();
+ fakeSdkDir = createTempFile(this.getClass().getSimpleName() + "_" + this.getName(), null);
+ mFakeSdk = SdkManagerTestUtil.makeFakeSdk(fakeSdkDir);
+ mSdkManager = SdkManager.createManager(mFakeSdk.getAbsolutePath(), mLog);
+ assertNotNull("sdkManager location was invalid", mSdkManager);
+
+ mAvdManager = new AvdManager(mSdkManager, mLog);
+ mAvdFolder = new File(mFakeSdk, "avdData");
+ mTarget = mSdkManager.getTargets()[0];
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ SdkManagerTestUtil.deleteDir(mFakeSdk);
+ }
+
+ public void txestDisplayEmptyAvdList() {
+ Main main = new Main();
+ main.setLogger(mLog);
+ mLog.clear();
+ main.displayAvdList(mAvdManager);
+ assertEquals("P Available Android Virtual Devices:\n", mLog.toString());
+ }
+
+ public void testDisplayAvdListOfOneNonSnapshot() {
+ Main main = new Main();
+ main.setLogger(mLog);
+ mAvdManager.createAvd(
+ mAvdFolder, this.getName(), mTarget, null, null, null, false, false, mLog);
+ mLog.clear();
+ main.displayAvdList(mAvdManager);
+ assertEquals(
+ "[P Available Android Virtual Devices:\n"
+ + ", P Name: " + this.getName() + "\n"
+ + ", P Path: " + mAvdFolder + "\n"
+ + ", P Target: Android 0.0 (API level 0)\n"
+ + ", P Skin: HVGA\n"
+ + "]",
+ mLog.toString());
+ }
+
+ public void testDisplayAvdListOfOneSnapshot() {
+ Main main = new Main();
+ main.setLogger(mLog);
+ mAvdManager.createAvd(
+ mAvdFolder, this.getName(), mTarget, null, null, null, false, true, mLog);
+ mLog.clear();
+ main.displayAvdList(mAvdManager);
+ assertEquals(
+ "[P Available Android Virtual Devices:\n"
+ + ", P Name: " + this.getName() + "\n"
+ + ", P Path: " + mAvdFolder + "\n"
+ + ", P Target: Android 0.0 (API level 0)\n"
+ + ", P Skin: HVGA\n"
+ + ", P Snapshot: true\n"
+ + "]",
+ mLog.toString());
+ }
+}
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/MockLog.java b/sdkmanager/app/tests/com/android/sdkmanager/MockLog.java
new file mode 100644
index 0000000..a8ca90a
--- /dev/null
+++ b/sdkmanager/app/tests/com/android/sdkmanager/MockLog.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 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.sdkmanager;
+
+import com.android.sdklib.ISdkLog;
+
+import java.util.ArrayList;
+import java.util.Formatter;
+
+public class MockLog implements ISdkLog {
+ private ArrayList<String> mMessages = new ArrayList<String>();
+
+ private void add(String code, String format, Object... args) {
+ mMessages.add(new Formatter().format(code + format, args).toString());
+ }
+
+ @Override
+ public void warning(String format, Object... args) {
+ add("W ", format, args);
+ }
+
+ @Override
+ public void printf(String format, Object... args) {
+ add("P ", format, args);
+ }
+
+ @Override
+ public void error(Throwable t, String format, Object... args) {
+ if (t != null) {
+ add("T", "%s", t.toString());
+ }
+ add("E ", format, args);
+ }
+
+ @Override
+ public String toString() {
+ return mMessages.toString();
+ }
+
+ public void clear() {
+ mMessages.clear();
+ }
+}
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/SdkCommandLineTest.java b/sdkmanager/app/tests/com/android/sdkmanager/SdkCommandLineTest.java
index 8206e2a..036d2ec 100644
--- a/sdkmanager/app/tests/com/android/sdkmanager/SdkCommandLineTest.java
+++ b/sdkmanager/app/tests/com/android/sdkmanager/SdkCommandLineTest.java
@@ -24,7 +24,7 @@ import junit.framework.TestCase;
public class SdkCommandLineTest extends TestCase {
private StdSdkLog mLog;
-
+
/**
* A mock version of the {@link SdkCommandLine} class that does not
* exits and discards its stdout/stderr output.
@@ -32,7 +32,7 @@ public class SdkCommandLineTest extends TestCase {
public static class MockSdkCommandLine extends SdkCommandLine {
private boolean mExitCalled;
private boolean mHelpCalled;
-
+
public MockSdkCommandLine(ISdkLog logger) {
super(logger);
}
@@ -48,12 +48,12 @@ public class SdkCommandLineTest extends TestCase {
protected void exit() {
mExitCalled = true;
}
-
+
@Override
protected void stdout(String format, Object... args) {
// discard
}
-
+
@Override
protected void stderr(String format, Object... args) {
// discard
@@ -62,7 +62,7 @@ public class SdkCommandLineTest extends TestCase {
public boolean wasExitCalled() {
return mExitCalled;
}
-
+
public boolean wasHelpCalled() {
return mHelpCalled;
}
@@ -139,4 +139,30 @@ public class SdkCommandLineTest extends TestCase {
assertEquals("target", c.getDirectObject());
assertFalse(c.isVerbose());
}
+
+ public final void testCreate_Avd() {
+ MockSdkCommandLine c = new MockSdkCommandLine(mLog);
+ c.parseArgs(new String[] { "create", "avd", "-t", "android-100", "-n", "myProject" });
+ assertFalse(c.wasHelpCalled());
+ assertFalse(c.wasExitCalled());
+ assertEquals("create", c.getVerb());
+ assertEquals("avd", c.getDirectObject());
+ assertFalse(c.getFlagSnapshot());
+ assertEquals("android-100", c.getParamTargetId());
+ assertEquals("myProject", c.getParamName());
+ assertFalse(c.isVerbose());
+ }
+
+ public final void testCreate_Avd_Snapshot() {
+ MockSdkCommandLine c = new MockSdkCommandLine(mLog);
+ c.parseArgs(new String[] { "create", "avd", "-t", "android-100", "-n", "myProject", "-a" });
+ assertFalse(c.wasHelpCalled());
+ assertFalse(c.wasExitCalled());
+ assertEquals("create", c.getVerb());
+ assertEquals("avd", c.getDirectObject());
+ assertTrue(c.getFlagSnapshot());
+ assertEquals("android-100", c.getParamTargetId());
+ assertEquals("myProject", c.getParamName());
+ assertFalse(c.isVerbose());
+ }
}
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java b/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java
new file mode 100644
index 0000000..96efb5c
--- /dev/null
+++ b/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 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.sdkmanager;
+
+import com.android.prefs.AndroidLocation;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class SdkManagerTestUtil {
+ /**
+ * Build enough of a skeleton SDK to make the tests pass.
+ *<p>
+ * Ideally this wouldn't touch the file system, but I'm not inclined to
+ * fiddle around with mock file systems just at the moment.
+ *
+ * @return an sdk manager to a fake sdk
+ * @throws IOException
+ */
+ public static File makeFakeSdk(File fakeSdk) throws IOException {
+ fakeSdk.delete();
+ fakeSdk.mkdirs();
+ AndroidLocation.resetFolder();
+ System.setProperty("user.home", fakeSdk.getAbsolutePath());
+ File addonsDir = new File(fakeSdk, SdkConstants.FD_ADDONS);
+ addonsDir.mkdir();
+ File toolsLibEmuDir = new File(fakeSdk, SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + "emulator");
+ toolsLibEmuDir.mkdirs();
+ new File(toolsLibEmuDir, "snapshots.img").createNewFile();
+ File platformsDir = new File(fakeSdk, SdkConstants.FD_PLATFORMS);
+
+ // Creating a fake target here on down
+ File targetDir = new File(platformsDir, "v0_0");
+ targetDir.mkdirs();
+ new File(targetDir, SdkConstants.FN_FRAMEWORK_LIBRARY).createNewFile();
+ new File(targetDir, SdkConstants.FN_FRAMEWORK_AIDL).createNewFile();
+ new File(targetDir, SdkConstants.FN_SOURCE_PROP).createNewFile();
+ File buildProp = new File(targetDir, SdkConstants.FN_BUILD_PROP);
+ FileWriter out = new FileWriter(buildProp);
+ out.write(SdkManager.PROP_VERSION_RELEASE + "=0.0\n");
+ out.write(SdkManager.PROP_VERSION_SDK + "=0\n");
+ out.write(SdkManager.PROP_VERSION_CODENAME + "=REL\n");
+ out.close();
+ File imagesDir = new File(targetDir, "images");
+ imagesDir.mkdirs();
+ new File(imagesDir, "userdata.img").createNewFile();
+ File skinsDir = new File(targetDir, "skins");
+ File hvgaDir = new File(skinsDir, "HVGA");
+ hvgaDir.mkdirs();
+ return fakeSdk;
+ }
+
+ /**
+ * Recursive delete directory. Mostly for fake SDKs.
+ *
+ * @param root directory to delete
+ */
+ public static void deleteDir(File root) {
+ if (root.exists()) {
+ for (File file : root.listFiles()) {
+ if (file.isDirectory()) {
+ deleteDir(file);
+ } else {
+ file.delete();
+ }
+ }
+ root.delete();
+ }
+ }
+
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
index b2c1326..09e3502 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -250,6 +250,13 @@ public final class SdkConstants {
public final static String OS_SDK_TOOLS_LIB_FOLDER =
OS_SDK_TOOLS_FOLDER + FD_LIB + File.separator;
+ /**
+ * Path of the lib directory relative to the sdk folder, or to a platform
+ * folder. This is an OS path, ending with a separator.
+ */
+ public final static String OS_SDK_TOOLS_LIB_EMULATOR_FOLDER = OS_SDK_TOOLS_LIB_FOLDER
+ + "emulator" + File.separator;
+
/** Path of the platform tools directory relative to the sdk folder.
* This is an OS path, ending with a separator. */
public final static String OS_SDK_PLATFORM_TOOLS_FOLDER = FD_PLATFORM_TOOLS + File.separator;
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
index 27d849c..eba8e07 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
@@ -29,6 +29,7 @@ import com.android.sdklib.io.FileWrapper;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
@@ -108,6 +109,13 @@ public final class AvdManager {
* @see #AVD_INI_IMAGES_1
*/
public final static String AVD_INI_IMAGES_2 = "image.sysdir.2"; //$NON-NLS-1$
+ /**
+ * AVD/config.ini key name representing the presence of the snapshots file.
+ * This property is for UI purposes only. It is not used by the emulator.
+ *
+ * @see #SNAPSHOTS_IMG
+ */
+ public final static String AVD_INI_SNAPSHOT_PRESENT = "snapshot.present"; //$NON-NLS-1$
/**
* Pattern to match pixel-sized skin "names", e.g. "320x480".
@@ -117,6 +125,7 @@ public final class AvdManager {
private final static String USERDATA_IMG = "userdata.img"; //$NON-NLS-1$
private final static String CONFIG_INI = "config.ini"; //$NON-NLS-1$
private final static String SDCARD_IMG = "sdcard.img"; //$NON-NLS-1$
+ private final static String SNAPSHOTS_IMG = "snapshots.img"; //$NON-NLS-1$
private final static String INI_EXTENSION = ".ini"; //$NON-NLS-1$
private final static Pattern INI_NAME_PATTERN = Pattern.compile("(.+)\\" + //$NON-NLS-1$
@@ -486,6 +495,19 @@ public final class AvdManager {
}
/**
+ * Creates a new AVD, but with no snapshot.
+ *
+ * See {@link #createAvd(File, String, IAndroidTarget, String, String, Map, boolean, boolean, ISdkLog)}
+ **/
+ @Deprecated
+ public AvdInfo createAvd(File avdFolder, String name, IAndroidTarget target, String skinName,
+ String sdcard, Map<String, String> hardwareConfig, boolean removePrevious,
+ ISdkLog log) {
+ return createAvd(avdFolder, name, target, skinName, sdcard, hardwareConfig, removePrevious,
+ false, log);
+ }
+
+ /**
* Creates a new AVD. It is expected that there is no existing AVD with this name already.
*
* @param avdFolder the data folder for the AVD. It will be created as needed.
@@ -496,13 +518,14 @@ public final class AvdManager {
* an existing sdcard image or a sdcard size (\d+, \d+K, \dM).
* @param hardwareConfig the hardware setup for the AVD. Can be null to use defaults.
* @param removePrevious If true remove any previous files.
+ * @param createSnapshot If true copy a blank snapshot image into the AVD.
* @param log the log object to receive action logs. Cannot be null.
* @return The new {@link AvdInfo} in case of success (which has just been added to the
* internal list) or null in case of failure.
*/
public AvdInfo createAvd(File avdFolder, String name, IAndroidTarget target,
String skinName, String sdcard, Map<String,String> hardwareConfig,
- boolean removePrevious, ISdkLog log) {
+ boolean removePrevious, boolean createSnapshot, ISdkLog log) {
if (log == null) {
throw new IllegalArgumentException("log cannot be null");
}
@@ -549,20 +572,9 @@ public final class AvdManager {
needCleanup = true;
return null;
}
-
- FileInputStream fis = new FileInputStream(userdataSrc);
-
File userdataDest = new File(avdFolder, USERDATA_IMG);
- FileOutputStream fos = new FileOutputStream(userdataDest);
-
- byte[] buffer = new byte[4096];
- int count;
- while ((count = fis.read(buffer)) != -1) {
- fos.write(buffer, 0, count);
- }
- fos.close();
- fis.close();
+ copyImageFile(userdataSrc, userdataDest);
// Config file.
HashMap<String, String> values = new HashMap<String, String>();
@@ -572,6 +584,22 @@ public final class AvdManager {
return null;
}
+ // Create the snapshot file
+ if (createSnapshot) {
+ String toolsLib = mSdkManager.getLocation() + File.separator
+ + SdkConstants.OS_SDK_TOOLS_LIB_EMULATOR_FOLDER;
+ File snapshotBlank = new File(toolsLib, SNAPSHOTS_IMG);
+ if (snapshotBlank.exists() == false) {
+ log.error(null, "Unable to find a '%2$s%1$s' file to copy into the AVD folder.",
+ SNAPSHOTS_IMG, toolsLib);
+ needCleanup = true;
+ return null;
+ }
+ File snapshotDest = new File(avdFolder, SNAPSHOTS_IMG);
+ copyImageFile(snapshotBlank, snapshotDest);
+ values.put(AVD_INI_SNAPSHOT_PRESENT, "true");
+ }
+
// Now the skin.
if (skinName == null || skinName.length() == 0) {
skinName = target.getDefaultSkin();
@@ -804,6 +832,28 @@ public final class AvdManager {
return null;
}
+ /** Copy the nominated file to the given destination.
+ * @param source
+ * @param destination
+ *
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void copyImageFile(File source, File destination)
+ throws FileNotFoundException, IOException {
+ FileInputStream fis = new FileInputStream(source);
+ FileOutputStream fos = new FileOutputStream(destination);
+
+ byte[] buffer = new byte[4096];
+ int count;
+ while ((count = fis.read(buffer)) != -1) {
+ fos.write(buffer, 0, count);
+ }
+
+ fos.close();
+ fis.close();
+ }
+
/**
* Returns the path to the target images folder as a relative path to the SDK, if the folder
* is not empty. If the image folder is empty or does not exist, <code>null</code> is returned.
@@ -1203,6 +1253,8 @@ public final class AvdManager {
}
}
+ // TODO: What about missing sdcard, skins, etc?
+
AvdStatus status;
if (avdPath == null) {
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
index 6dbdca6..4411034 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
@@ -23,8 +23,8 @@ import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.avd.HardwareProperties;
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
+import com.android.sdklib.internal.avd.HardwareProperties;
import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdklib.io.FileWrapper;
@@ -73,8 +73,8 @@ import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
-import java.util.TreeMap;
import java.util.Map.Entry;
+import java.util.TreeMap;
import java.util.regex.Matcher;
/**
@@ -110,6 +110,8 @@ final class AvdCreationDialog extends GridDialog {
private Button mBrowseSdCard;
private Button mSdCardFileRadio;
+ private Button mSnapshotCheck;
+
private Button mSkinListRadio;
private Combo mSkinCombo;
@@ -346,6 +348,22 @@ final class AvdCreationDialog extends GridDialog {
mSdCardSizeRadio.setSelection(true);
enableSdCardWidgets(true);
+ // --- snapshot group
+
+ label = new Label(parent, SWT.NONE);
+ label.setText("Snapshot:");
+ label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
+ false, false));
+
+ final Group snapshotGroup = new Group(parent, SWT.NONE);
+ snapshotGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ snapshotGroup.setLayout(new GridLayout(3, false));
+
+ mSnapshotCheck = new Button(snapshotGroup, SWT.CHECK);
+ mSnapshotCheck.setText("Enabled");
+ mSnapshotCheck.setToolTipText(
+ "Emulator's state will be persisted between emulator executions");
+
// --- skin group
label = new Label(parent, SWT.NONE);
label.setText("Skin:");
@@ -715,6 +733,11 @@ final class AvdCreationDialog extends GridDialog {
}
}
+ String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
+ if (snapshots != null && snapshots.length() > 0) {
+ mSnapshotCheck.setSelection(snapshots.equals("true"));
+ }
+
mProperties.clear();
mProperties.putAll(props);
@@ -723,6 +746,7 @@ final class AvdCreationDialog extends GridDialog {
mProperties.remove(AvdManager.AVD_INI_SKIN_NAME);
mProperties.remove(AvdManager.AVD_INI_SDCARD_SIZE);
mProperties.remove(AvdManager.AVD_INI_SDCARD_PATH);
+ mProperties.remove(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
mProperties.remove(AvdManager.AVD_INI_IMAGES_1);
mProperties.remove(AvdManager.AVD_INI_IMAGES_2);
mHardwareViewer.refresh();
@@ -1138,6 +1162,7 @@ final class AvdCreationDialog extends GridDialog {
}
boolean force = mForceCreation.getSelection();
+ boolean snapshot = mSnapshotCheck.getSelection();
boolean success = false;
AvdInfo avdInfo = mAvdManager.createAvd(
@@ -1148,6 +1173,7 @@ final class AvdCreationDialog extends GridDialog {
sdName,
mProperties,
force,
+ snapshot,
log);
success = avdInfo != null;
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java
index a845056..409c25d 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java
@@ -127,6 +127,11 @@ final class AvdDetailsDialog extends Dialog {
displayValue(c, "SD Card:", sdcard);
}
+ String snapshot = properties.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
+ if (snapshot != null) {
+ displayValue(c, "Snapshot:", snapshot);
+ }
+
// display other hardware
HashMap<String, String> copy = new HashMap<String, String>(properties);
// remove stuff we already displayed (or that we don't want to display)
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
index e002ef3..5e26a41 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
@@ -1037,9 +1037,17 @@ public final class AvdSelector {
list.add(path);
list.add("-avd"); //$NON-NLS-1$
list.add(avdName);
- if (dialog.getWipeData()) {
+ if (dialog.hasWipeData()) {
list.add("-wipe-data"); //$NON-NLS-1$
}
+ if (dialog.hasSnapshot()) {
+ if (!dialog.hasSnapshotLaunch()) {
+ list.add("-no-snapshot-load");
+ }
+ if (!dialog.hasSnapshotSave()) {
+ list.add("-no-snapshot-save");
+ }
+ }
float scale = dialog.getScale();
if (scale != 0.f) {
// do the rounding ourselves. This is because %.1f will write .4899 as .4
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java
index a2a9218..77f47d1 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java
@@ -56,13 +56,14 @@ import java.util.regex.Pattern;
* <li>-wipe-data</li>
* <li>-scale</li>
* </ul>
- *
* Values are stored (in the class as static field) to be reused while the app is still running.
- * The Monitor dpi is stored in the settings if availabe.
+ * The Monitor dpi is stored in the settings if available.
*/
final class AvdStartDialog extends GridDialog {
// static field to reuse values during the same session.
private static boolean sWipeData = false;
+ private static boolean sSnapshotSave = true;
+ private static boolean sSnapshotLaunch = true;
private static int sMonitorDpi = 72; // used if there's no setting controller.
private static final Map<String, String> sSkinScaling = new HashMap<String, String>();
@@ -84,6 +85,10 @@ final class AvdStartDialog extends GridDialog {
private String mSkinDisplay;
private boolean mEnableScaling = true;
private Label mScaleField;
+ private boolean mHasSnapshot = true;
+ private boolean mSnapshotSave = true;
+ private boolean mSnapshotLaunch = true;
+ private Button mSnapshotLaunchCheckbox;
AvdStartDialog(Shell parentShell, AvdInfo avd, String sdkLocation,
SettingsController settingsController) {
@@ -101,7 +106,7 @@ final class AvdStartDialog extends GridDialog {
computeSkinData();
}
- public boolean getWipeData() {
+ public boolean hasWipeData() {
return mWipeData;
}
@@ -239,6 +244,36 @@ final class AvdStartDialog extends GridDialog {
@Override
public void widgetSelected(SelectionEvent arg0) {
mWipeData = wipeButton.getSelection();
+ updateSnapshotLaunchAvailability();
+ }
+ });
+
+ Map<String, String> prop = mAvd.getProperties();
+ String snapshotPresent = prop.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
+ mHasSnapshot = (snapshotPresent != null) && snapshotPresent.equals("true");
+
+ mSnapshotLaunchCheckbox = new Button(parent, SWT.CHECK);
+ mSnapshotLaunchCheckbox.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 2;
+ mSnapshotLaunchCheckbox.setText("Launch from snapshot");
+ updateSnapshotLaunchAvailability();
+ mSnapshotLaunchCheckbox.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ mSnapshotLaunch = mSnapshotLaunchCheckbox.getSelection();
+ }
+ });
+
+ final Button snapshotSaveCheckbox = new Button(parent, SWT.CHECK);
+ snapshotSaveCheckbox.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 2;
+ snapshotSaveCheckbox.setText("Save to snapshot");
+ snapshotSaveCheckbox.setSelection((mSnapshotSave = sSnapshotSave) && mHasSnapshot);
+ snapshotSaveCheckbox.setEnabled(mHasSnapshot);
+ snapshotSaveCheckbox.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ mSnapshotSave = snapshotSaveCheckbox.getSelection();
}
});
@@ -303,6 +338,14 @@ final class AvdStartDialog extends GridDialog {
// and then the wipe-data checkbox
sWipeData = mWipeData;
+ // and the snapshot handling if those checkboxes are enabled.
+ if (mHasSnapshot) {
+ sSnapshotSave = mSnapshotSave;
+ if (!mWipeData) {
+ sSnapshotLaunch = mSnapshotLaunch;
+ }
+ }
+
// finally continue with the ok action
super.okPressed();
}
@@ -520,4 +563,36 @@ final class AvdStartDialog extends GridDialog {
return false;
}
+
+ /**
+ * @return Whether there's a snapshot file available.
+ */
+ public boolean hasSnapshot() {
+ return mHasSnapshot;
+ }
+
+ /**
+ * @return Whether to launch and load snapshot.
+ */
+ public boolean hasSnapshotLaunch() {
+ return mSnapshotLaunch && !hasWipeData();
+ }
+
+ /**
+ * @return Whether to preserve emulator state to snapshot.
+ */
+ public boolean hasSnapshotSave() {
+ return mSnapshotSave;
+ }
+
+ /**
+ * Updates snapshot launch availability, for when mWipeData value changes.
+ */
+ private void updateSnapshotLaunchAvailability() {
+ boolean enabled = !mWipeData && mHasSnapshot;
+ mSnapshotLaunchCheckbox.setEnabled(enabled);
+ mSnapshotLaunch = enabled && sSnapshotLaunch;
+ mSnapshotLaunchCheckbox.setSelection(mSnapshotLaunch);
+ }
+
}