From 2bb7ab0c55cc3e848f2c31601018637e13be7fac Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 22 Jan 2010 18:56:10 -0800 Subject: [PATCH] ADT NPW: cleanup minSdkVersion resolution for samples. This fixes a couple quirks in NPW: - When you select a sample, its minSdkVersion is now used as-is but the currently selected target is not changed to match. Otherwise it invalidates the list of samples you're trying to import from... - This allows for samples with no minSdkVersion to properly import with an empty field. - Same issue if you were to manually edit the field after the fact. Also renamed IAndroidTarget.isCompatibleBaseFor() to IAndroidTarget.canRunOn(), which is way more readable. This also "fixes" bug 2346838 -- kind of, the bug was obsolete since I had added the new sample mode but there was another quirk instead (it was reverting the target so it invalidated the sample you were trying to import... see point #1 above.) Change-Id: If2487632484fa5646bea7fe2625a2a55e5d26c50 --- .../internal/launch/AndroidLaunchController.java | 9 +-- .../adt/internal/launch/DeviceChooserDialog.java | 4 +- .../wizards/newproject/NewProjectCreationPage.java | 83 +++++++++++++--------- .../sdklib/src/com/android/sdklib/AddOnTarget.java | 6 +- .../src/com/android/sdklib/AndroidVersion.java | 2 +- .../src/com/android/sdklib/IAndroidTarget.java | 11 ++- .../src/com/android/sdklib/PlatformTarget.java | 2 +- .../internal/repository/MockAddonPackage.java | 2 +- .../internal/repository/MockPlatformPackage.java | 2 +- .../sdkuilib/internal/widgets/AvdSelector.java | 2 +- 10 files changed, 72 insertions(+), 51 deletions(-) diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java index 16dad906e..4c8621ee3 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java @@ -347,7 +347,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener AvdInfo preferredAvd = null; if (config.mAvdName != null) { preferredAvd = avdManager.getAvd(config.mAvdName, true /*validAvdOnly*/); - if (projectTarget.isCompatibleBaseFor(preferredAvd.getTarget()) == false) { + if (projectTarget.canRunOn(preferredAvd.getTarget()) == false) { preferredAvd = null; AdtPlugin.printErrorToConsole(project, String.format( @@ -394,7 +394,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener String deviceAvd = d.getAvdName(); if (deviceAvd != null) { // physical devices return null. AvdInfo info = avdManager.getAvd(deviceAvd, true /*validAvdOnly*/); - if (info != null && projectTarget.isCompatibleBaseFor(info.getTarget())) { + if (info != null && projectTarget.canRunOn(info.getTarget())) { compatibleRunningAvds.put(d, info); } } else { @@ -547,9 +547,9 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener AvdInfo[] avds = avdManager.getValidAvds(); AvdInfo defaultAvd = null; for (AvdInfo avd : avds) { - if (projectTarget.isCompatibleBaseFor(avd.getTarget())) { + if (projectTarget.canRunOn(avd.getTarget())) { // at this point we can ignore the code name issue since - // IAndroidTarget.isCompatibleBaseFor() will already have filtered the non + // IAndroidTarget.canRunOn() will already have filtered the non // compatible AVDs. if (defaultAvd == null || avd.getTarget().getVersion().getApiLevel() < @@ -1212,6 +1212,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener * @return false if cancelled by the monitor * @throws CoreException */ + @SuppressWarnings("deprecation") public static boolean connectRemoteDebugger(int debugPort, AndroidLaunch launch, IProgressMonitor monitor) throws CoreException { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java index 315f456ac..bb4d580dd 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java @@ -146,7 +146,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener if (info == null) { return mWarningImage; } - return mProjectTarget.isCompatibleBaseFor(info.getTarget()) ? + return mProjectTarget.canRunOn(info.getTarget()) ? mMatchImage : mNoMatchImage; } } @@ -687,7 +687,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener public boolean accept(AvdInfo avd) { if (mDevices != null) { for (IDevice d : mDevices) { - if (mProjectTarget.isCompatibleBaseFor(avd.getTarget()) == false || + if (mProjectTarget.canRunOn(avd.getTarget()) == false || avd.getName().equals(d.getAvdName())) { return false; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreationPage.java index bd212cb4e..d14447401 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreationPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreationPage.java @@ -923,6 +923,15 @@ public class NewProjectCreationPage extends WizardPage { String minSdkVersion = mInfo.getMinSdkVersion(); + // If there's a current target defined, we do not allow to change it when + // operating in the create-from-sample mode -- since the available sample list + // is tied to the current target, so changing it would invalidate the project we're + // trying to load in the first place. + IAndroidTarget currentTarget = mInfo.getSdkTarget(); + if (currentTarget != null && mInfo.isCreateFromSample()) { + return; + } + // Before changing, compare with the currently selected one, if any. // There can be multiple targets with the same sdk api version, so don't change // it if it's already at the right version. @@ -1100,44 +1109,51 @@ public class NewProjectCreationPage extends WizardPage { // Select the target matching the manifest's sdk or build properties, if any IAndroidTarget foundTarget = null; + // This is the target currently in the UI IAndroidTarget currentTarget = mInfo.getSdkTarget(); - ProjectProperties p = ProjectProperties.create(projectLocation, null); - if (p != null) { - // Check the {build|default}.properties files if present - p.merge(PropertyType.BUILD).merge(PropertyType.DEFAULT); - String v = p.getProperty(ProjectProperties.PROPERTY_TARGET); - IAndroidTarget target = Sdk.getCurrent().getTargetFromHashString(v); - // We can change the current target if: - // - we found a new target - // - there is no current target - // - there is a current target but the new target is not <= to the current one. - if (target != null && - (currentTarget == null || !target.isCompatibleBaseFor(currentTarget))) { - foundTarget = target; + // If there's a current target defined, we do not allow to change it when + // operating in the create-from-sample mode -- since the available sample list + // is tied to the current target, so changing it would invalidate the project we're + // trying to load in the first place. + if (currentTarget == null || !mInfo.isCreateFromSample()) { + ProjectProperties p = ProjectProperties.create(projectLocation, null); + if (p != null) { + // Check the {build|default}.properties files if present + p.merge(PropertyType.BUILD).merge(PropertyType.DEFAULT); + String v = p.getProperty(ProjectProperties.PROPERTY_TARGET); + IAndroidTarget desiredTarget = Sdk.getCurrent().getTargetFromHashString(v); + // We can change the current target if: + // - we found a new desired target + // - there is no current target + // - or the current target can't run the desired target + if (desiredTarget != null && + (currentTarget == null || !desiredTarget.canRunOn(currentTarget))) { + foundTarget = desiredTarget; + } } - } - if (foundTarget == null && minSdkVersion != null) { - // Otherwise try to match the requested sdk version - for (IAndroidTarget target : mSdkTargetSelector.getTargets()) { - if (target != null && - target.getVersion().equals(minSdkVersion) && - (currentTarget == null || !target.isCompatibleBaseFor(currentTarget))) { - foundTarget = target; - break; + if (foundTarget == null && minSdkVersion != null) { + // Otherwise try to match the requested min-sdk-version if we find an + // exact match, regardless of the currently selected target. + for (IAndroidTarget existingTarget : mSdkTargetSelector.getTargets()) { + if (existingTarget != null && + existingTarget.getVersion().equals(minSdkVersion)) { + foundTarget = existingTarget; + break; + } } } - } - if (foundTarget == null) { - // Or last attemp, try to match a sample project location - for (IAndroidTarget target : mSdkTargetSelector.getTargets()) { - if (target != null && - projectLocation.startsWith(target.getLocation()) && - (currentTarget == null || !target.isCompatibleBaseFor(currentTarget))) { - foundTarget = target; - break; + if (foundTarget == null) { + // Or last attempt, try to match a sample project location and use it + // if we find an exact match, regardless of the currently selected target. + for (IAndroidTarget existingTarget : mSdkTargetSelector.getTargets()) { + if (existingTarget != null && + projectLocation.startsWith(existingTarget.getLocation())) { + foundTarget = existingTarget; + break; + } } } } @@ -1146,9 +1162,8 @@ public class NewProjectCreationPage extends WizardPage { mSdkTargetSelector.setSelection(foundTarget); } else { mInternalMinSdkVersionUpdate = true; - if (minSdkVersion != null) { - mMinSdkVersionField.setText(minSdkVersion); - } + // It's OK for an import to not a minSdkVersion and we should respect it. + mMinSdkVersionField.setText(minSdkVersion == null ? "" : minSdkVersion); //$NON-NLS-1$ mInternalMinSdkVersionUpdate = false; } } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java index 918409957..2a55a6858 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java @@ -212,7 +212,7 @@ final class AddOnTarget implements IAndroidTarget { return mVendorId; } - public boolean isCompatibleBaseFor(IAndroidTarget target) { + public boolean canRunOn(IAndroidTarget target) { // basic test if (target == this) { return true; @@ -228,7 +228,7 @@ final class AddOnTarget implements IAndroidTarget { // The receiver is an add-on. There are 2 big use cases: The add-on has libraries // or the add-on doesn't (in which case we consider it a platform). if (mLibraries == null || mLibraries.length == 0) { - return mBasePlatform.isCompatibleBaseFor(target); + return mBasePlatform.canRunOn(target); } else { // the only targets that can run the receiver are the same add-on in the same or later // versions. @@ -241,7 +241,7 @@ final class AddOnTarget implements IAndroidTarget { // now check the version. At this point since we checked the add-on part, // we can revert to the basic check on version/codename which are done by the // base platform already. - return mBasePlatform.isCompatibleBaseFor(target); + return mBasePlatform.canRunOn(target); } } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java index 9315c7dbe..7674e76c3 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java @@ -161,7 +161,7 @@ public final class AndroidVersion implements Comparable { *

* Be aware that this is not a perfect test, as other properties could break compatibility * despite this method returning true. For a more comprehensive test, see - * {@link IAndroidTarget#isCompatibleBaseFor(IAndroidTarget)}. + * {@link IAndroidTarget#canRunOn(IAndroidTarget)}. *

* Nevertheless, when testing if an application can run on a device (where there is no * access to the list of optional libraries), this method can give a good indication of whether diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java index 095a593e4..2bc250c4a 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java @@ -180,12 +180,17 @@ public interface IAndroidTarget extends Comparable { /** * Returns whether the given target is compatible with the receiver. - *

A target is considered compatible if applications developed for the receiver can run on - * the given target. + *

+ * This means that a project using the receiver's target can run on the given target. + *
+ * Example: + *

+     * CupcakeTarget.canRunOn(DonutTarget) == true
+     * 
. * * @param target the IAndroidTarget to test. */ - boolean isCompatibleBaseFor(IAndroidTarget target); + boolean canRunOn(IAndroidTarget target); /** * Returns a string able to uniquely identify a target. diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java index 035df21f4..63a117d50 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java @@ -191,7 +191,7 @@ final class PlatformTarget implements IAndroidTarget { return NO_USB_ID; } - public boolean isCompatibleBaseFor(IAndroidTarget target) { + public boolean canRunOn(IAndroidTarget target) { // basic test if (target == this) { return true; diff --git a/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockAddonPackage.java b/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockAddonPackage.java index 4d4199f4e..5ed9751c9 100755 --- a/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockAddonPackage.java +++ b/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockAddonPackage.java @@ -123,7 +123,7 @@ public class MockAddonPackage extends AddonPackage { return false; } - public boolean isCompatibleBaseFor(IAndroidTarget target) { + public boolean canRunOn(IAndroidTarget target) { throw new UnsupportedOperationException("Implement this as needed for tests"); } diff --git a/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockPlatformPackage.java b/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockPlatformPackage.java index b840b82bc..8453e4e6f 100755 --- a/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockPlatformPackage.java +++ b/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockPlatformPackage.java @@ -156,7 +156,7 @@ public class MockPlatformPackage extends PlatformPackage { return true; } - public boolean isCompatibleBaseFor(IAndroidTarget target) { + public boolean canRunOn(IAndroidTarget target) { throw new UnsupportedOperationException("Implement this as needed for tests"); } 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 b97d8fb55..91ada7ee0 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 @@ -169,7 +169,7 @@ public final class AvdSelector { public boolean accept(AvdInfo avd) { if (avd != null) { - return mTarget.isCompatibleBaseFor(avd.getTarget()); + return mTarget.canRunOn(avd.getTarget()); } return false; -- 2.11.0