diff options
author | Raphael <raphael@google.com> | 2010-03-25 15:15:53 -0700 |
---|---|---|
committer | Raphael <raphael@google.com> | 2010-03-26 14:07:27 -0700 |
commit | 31dcfe7ab21a0ca71c6c51dba6d41b1d767cf028 (patch) | |
tree | e8a39e6036a305a57cfe1f1f60eaa45208a9bc61 | |
parent | 874a96cd7d5e8f371f4495668c04e9a3dcce17ce (diff) | |
download | sdk-31dcfe7ab21a0ca71c6c51dba6d41b1d767cf028.zip sdk-31dcfe7ab21a0ca71c6c51dba6d41b1d767cf028.tar.gz sdk-31dcfe7ab21a0ca71c6c51dba6d41b1d767cf028.tar.bz2 |
SDK Manager: correctly handle lack of AvdManager
Digit's issue in SDK Bug 2535112 was that AndroidLocation failed
to get the SDK home dir; consequently the SdkManager failed to
create an AvdManager and was using a null ptr everywhere.
This CL addresses the core issue here:
- The New AVD button should be grayed if there is AvdManager.
- UpdaterData.initSdk was catching the error and printing an
error log that is not shown in the UI. There's now an explicit
dialog box that explains the error and how to solve it.
- UpdaterWindow now aborts if the above dialog is shown. There's
no need to keep the SDK Manager window around -- OK maybe that's
a bit harsh since the SDK download/install part can stil lbe used
by do we really want to deal with an half-functional window?
No we don't really want that use-case. Let's force the user to
fix it.
- Fixed the AndroidLocation error message to something more usable.
Most people can set an environment variable, however few know
how to "set up the user.home property" (I don't even know how
to do that.)
- Display the AVD base folder in the AVD page.
Change-Id: I2b9dbc7180e4bb3ff696de257bb260e808301d2d
6 files changed, 88 insertions, 13 deletions
diff --git a/androidprefs/src/com/android/prefs/AndroidLocation.java b/androidprefs/src/com/android/prefs/AndroidLocation.java index 446c426..4936489 100644 --- a/androidprefs/src/com/android/prefs/AndroidLocation.java +++ b/androidprefs/src/com/android/prefs/AndroidLocation.java @@ -52,7 +52,7 @@ public final class AndroidLocation { // if the above failed, we throw an exception. if (home == null) { throw new AndroidLocationException( - "Unable to get the home directory. Make sure the user.home property is set up"); + "Unable to get the home directory. Make sure the environment variable ANDROID_SDK_HOME is set up"); } else { sPrefsLocation = home + File.separator + ".android" + 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 8df6935..cc679cf 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 @@ -240,7 +240,7 @@ public final class AvdManager { */ public static File getIniFile(String name) throws AndroidLocationException { String avdRoot; - avdRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD; + avdRoot = getBaseAvdFolder(); return new File(avdRoot, name + INI_EXTENSION); } @@ -351,6 +351,15 @@ public final class AvdManager { private final SdkManager mSdkManager; /** + * Returns the base folder where AVDs are created. + * + * @throws AndroidLocationException + */ + public static String getBaseAvdFolder() throws AndroidLocationException { + return AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD; + } + + /** * Creates an AVD Manager for a given SDK represented by a {@link SdkManager}. * @param sdkManager The SDK. * @param log The log object to receive the log of the initial loading of the AVDs. @@ -1049,7 +1058,7 @@ public final class AvdManager { */ private File[] buildAvdFilesList() throws AndroidLocationException { // get the Android prefs location. - String avdRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD; + String avdRoot = AvdManager.getBaseAvdFolder(); // ensure folder validity. File folder = new File(avdRoot); diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java index 8e63cf9..eb1dccd 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java @@ -16,11 +16,14 @@ package com.android.sdkuilib.internal.repository;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdkuilib.internal.widgets.AvdSelector;
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
import com.android.sdkuilib.repository.UpdaterWindow.ISdkListener;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
@@ -50,7 +53,17 @@ public class AvdManagerPage extends Composite implements ISdkListener { parent.setLayout(new GridLayout(1, false));
Label label = new Label(parent, SWT.NONE);
- label.setText("List of existing Android Virtual Devices:");
+ label.setLayoutData(new GridData());
+
+ try {
+ label.setText(String.format(
+ "List of existing Android Virtual Devices located at %s",
+ AvdManager.getBaseAvdFolder()));
+ } catch (AndroidLocationException e) {
+ // We shouldn't be getting here anymore: UpdaterData.initSdk() will
+ // no longer complete if the AvdManager failed to be created.
+ label.setText("Error: Please define the environment variable ANDROID_SDK_HOME.");
+ }
mAvdSelector = new AvdSelector(parent,
mUpdaterData.getOsSdkRoot(),
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java index 5e40e5b..3d5405c 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java @@ -18,6 +18,7 @@ package com.android.sdkuilib.internal.repository; import com.android.prefs.AndroidLocation.AndroidLocationException;
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.repository.AddonPackage;
@@ -70,6 +71,8 @@ class UpdaterData { private Shell mWindowShell;
+ private AndroidLocationException mAvdManagerInitError;
+
/**
* Creates a new updater data.
*
@@ -167,6 +170,36 @@ class UpdaterData { return mWindowShell;
}
+ /**
+ * Check if any error occurred during initialization.
+ * If it did, display an error message.
+ *
+ * @return True if an error occurred, false if we should continue.
+ */
+ public boolean checkIfInitFailed() {
+ if (mAvdManagerInitError != null) {
+ String example;
+ if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) {
+ example = "%USERPROFILE%"; //$NON-NLS-1$
+ } else {
+ example = "~"; //$NON-NLS-1$
+ }
+
+ MessageDialog.openError(mWindowShell,
+ "Android Virtual Devices Manager",
+ String.format(
+ "The AVD manager normally uses the user's profile directory to store " +
+ "AVD files. However it failed to find the default profile directory. " +
+ "\n" +
+ "To fix this please set the environment variable ANDROID_SDK_HOME to " +
+ "a valid path such as \"%s\".",
+ example));
+
+ return true;
+ }
+ return false;
+ }
+
// -----
/**
@@ -178,7 +211,15 @@ class UpdaterData { mAvdManager = null; // remove the old one if needed.
mAvdManager = new AvdManager(mSdkManager, mSdkLog);
} catch (AndroidLocationException e) {
- mSdkLog.error(e, "Unable to read AVDs");
+ mSdkLog.error(e, "Unable to read AVDs: " + e.toString()); //$NON-NLS-1$
+
+ // Note: we used to continue here, but the thing is that
+ // mAvdManager==null so nothing is really going to work as
+ // expected. Let's just display an error later in checkIfInitFailed()
+ // and abort right there. This step is just too early in the SWT
+ // setup process to display a message box yet.
+
+ mAvdManagerInitError = e;
}
// notify adapters/parsers
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java index 4a41e4d..eda46e5 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java @@ -106,12 +106,12 @@ public class UpdaterWindowImpl { mAndroidSdkUpdater.open();
mAndroidSdkUpdater.layout();
- postCreate(); //$hide$ (hide from SWT designer)
-
- Display display = Display.getDefault();
- while (!mAndroidSdkUpdater.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
+ if (postCreate()) { //$hide$ (hide from SWT designer)
+ Display display = Display.getDefault();
+ while (!mAndroidSdkUpdater.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
}
}
@@ -257,8 +257,10 @@ public class UpdaterWindowImpl { /**
* Once the UI has been created, initializes the content.
* This creates the pages, selects the first one, setup sources and scan for local folders.
+ *
+ * Returns true if we should show the window.
*/
- private void postCreate() {
+ private boolean postCreate() {
mUpdaterData.setWindowShell(getShell());
mTaskFactory = new ProgressTaskFactory(getShell());
mUpdaterData.setTaskFactory(mTaskFactory);
@@ -285,11 +287,18 @@ public class UpdaterWindowImpl { setupSources();
initializeSettings();
+
+ if (mUpdaterData.checkIfInitFailed()) {
+ return false;
+ }
+
mUpdaterData.notifyListeners(true /*init*/);
if (mRequestAutoUpdate) {
mUpdaterData.updateOrInstallAll(null /*selectedArchives*/);
}
+
+ return true;
}
/**
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 60a3c82..fe686dc 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 @@ -362,6 +362,7 @@ public final class AvdSelector { adjustColumnsWidth(mTable, column0, column1, column2, column3); setupSelectionListener(mTable); fillTable(mTable); + setEnabled(true); } /** @@ -588,7 +589,8 @@ public final class AvdSelector { * @param enabled the new enabled state. */ public void setEnabled(boolean enabled) { - mIsEnabled = enabled; + // We can only enable widgets if the AVD Manager is defined. + mIsEnabled = enabled && mAvdManager != null; mTable.setEnabled(mIsEnabled); mRefreshButton.setEnabled(mIsEnabled); @@ -837,6 +839,7 @@ public final class AvdSelector { mAvdManager, mImageFactory, mSdkLog); + if (dlg.open() == Window.OK) { refresh(false /*reload*/); } |