Merge change Ib096f1f0 into eclair
* changes: SDK Manager: suggest install of new platforms, addons or extra packages.
This commit is contained in:
@@ -36,6 +36,16 @@ import java.util.Map.Entry;
|
|||||||
*/
|
*/
|
||||||
class CommandLineProcessor {
|
class CommandLineProcessor {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Steps needed to add a new action:
|
||||||
|
* - Each action is defined as a "verb object" followed by parameters.
|
||||||
|
* - Either reuse a VERB_ constant or define a new one.
|
||||||
|
* - Either reuse an OBJECT_ constant or define a new one.
|
||||||
|
* - Add a new entry to mAction with a one-line help summary.
|
||||||
|
* - In the constructor, add a define() call for each parameter (either mandatory
|
||||||
|
* or optional) for the given action.
|
||||||
|
*/
|
||||||
|
|
||||||
/** Internal verb name for internally hidden flags. */
|
/** Internal verb name for internally hidden flags. */
|
||||||
public final static String GLOBAL_FLAG_VERB = "@@internal@@";
|
public final static String GLOBAL_FLAG_VERB = "@@internal@@";
|
||||||
|
|
||||||
@@ -57,10 +67,14 @@ class CommandLineProcessor {
|
|||||||
/**
|
/**
|
||||||
* Action definitions.
|
* Action definitions.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
* This list serves two purposes: first it is used to know which verb/object
|
||||||
|
* actions are acceptable on the command-line; second it provides a summary
|
||||||
|
* for each action that is printed in the help.
|
||||||
|
* <p/>
|
||||||
* Each entry is a string array with:
|
* Each entry is a string array with:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li> the verb.
|
* <li> the verb.
|
||||||
* <li> a direct object (use #NO_VERB_OBJECT if there's no object).
|
* <li> a direct object (use {@link #NO_VERB_OBJECT} if there's no object).
|
||||||
* <li> a description.
|
* <li> a description.
|
||||||
* <li> an alternate form for the object (e.g. plural).
|
* <li> an alternate form for the object (e.g. plural).
|
||||||
* </ul>
|
* </ul>
|
||||||
@@ -81,6 +95,15 @@ class CommandLineProcessor {
|
|||||||
/** Logger */
|
/** Logger */
|
||||||
private final ISdkLog mLog;
|
private final ISdkLog mLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new command-line processor.
|
||||||
|
*
|
||||||
|
* @param logger An SDK logger object. Must not be null.
|
||||||
|
* @param actions The list of actions recognized on the command-line.
|
||||||
|
* See the javadoc of {@link #mActions} for more details.
|
||||||
|
*
|
||||||
|
* @see #mActions
|
||||||
|
*/
|
||||||
public CommandLineProcessor(ISdkLog logger, String[][] actions) {
|
public CommandLineProcessor(ISdkLog logger, String[][] actions) {
|
||||||
mLog = logger;
|
mLog = logger;
|
||||||
mActions = actions;
|
mActions = actions;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
|
|||||||
import com.android.sdklib.xml.AndroidXPathFactory;
|
import com.android.sdklib.xml.AndroidXPathFactory;
|
||||||
import com.android.sdkmanager.internal.repository.AboutPage;
|
import com.android.sdkmanager.internal.repository.AboutPage;
|
||||||
import com.android.sdkmanager.internal.repository.SettingsPage;
|
import com.android.sdkmanager.internal.repository.SettingsPage;
|
||||||
|
import com.android.sdkuilib.internal.repository.LocalPackagesPage;
|
||||||
import com.android.sdkuilib.repository.UpdaterWindow;
|
import com.android.sdkuilib.repository.UpdaterWindow;
|
||||||
|
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
@@ -243,7 +244,11 @@ public class Main {
|
|||||||
updateTestProject();
|
updateTestProject();
|
||||||
|
|
||||||
} else if (verb == null && directObject == null) {
|
} else if (verb == null && directObject == null) {
|
||||||
showMainWindow();
|
showMainWindow(false /*autoUpdate*/);
|
||||||
|
|
||||||
|
} else if (SdkCommandLine.VERB_UPDATE.equals(verb) &&
|
||||||
|
SdkCommandLine.OBJECT_SDK.equals(directObject)) {
|
||||||
|
showMainWindow(true /*autoUpdate*/);
|
||||||
|
|
||||||
} else if (SdkCommandLine.VERB_UPDATE.equals(verb) &&
|
} else if (SdkCommandLine.VERB_UPDATE.equals(verb) &&
|
||||||
SdkCommandLine.OBJECT_ADB.equals(directObject)) {
|
SdkCommandLine.OBJECT_ADB.equals(directObject)) {
|
||||||
@@ -257,7 +262,7 @@ public class Main {
|
|||||||
/**
|
/**
|
||||||
* Display the main SdkManager app window
|
* Display the main SdkManager app window
|
||||||
*/
|
*/
|
||||||
private void showMainWindow() {
|
private void showMainWindow(boolean autoUpdate) {
|
||||||
try {
|
try {
|
||||||
// display a message talking about the command line version
|
// display a message talking about the command line version
|
||||||
System.out.printf("No command line parameters provided, launching UI.\n" +
|
System.out.printf("No command line parameters provided, launching UI.\n" +
|
||||||
@@ -269,6 +274,10 @@ public class Main {
|
|||||||
false /*userCanChangeSdkRoot*/);
|
false /*userCanChangeSdkRoot*/);
|
||||||
window.registerPage("Settings", SettingsPage.class);
|
window.registerPage("Settings", SettingsPage.class);
|
||||||
window.registerPage("About", AboutPage.class);
|
window.registerPage("About", AboutPage.class);
|
||||||
|
if (autoUpdate) {
|
||||||
|
window.setInitialPage(LocalPackagesPage.class);
|
||||||
|
window.setRequestAutoUpdate(true);
|
||||||
|
}
|
||||||
window.open();
|
window.open();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -353,12 +362,14 @@ public class Main {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
errorAndExit("Unable to resolve Main project's directory: %1$s",
|
errorAndExit("Unable to resolve Main project's directory: %1$s",
|
||||||
pathToMainProject);
|
pathToMainProject);
|
||||||
|
return; // help Eclipse static analyzer understand we'll never execute the rest.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentProject.isDirectory() == false) {
|
if (parentProject.isDirectory() == false) {
|
||||||
errorAndExit("Main project's directory does not exist: %1$s",
|
errorAndExit("Main project's directory does not exist: %1$s",
|
||||||
pathToMainProject);
|
pathToMainProject);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now look for a manifest in there
|
// now look for a manifest in there
|
||||||
@@ -366,6 +377,7 @@ public class Main {
|
|||||||
if (manifest.isFile() == false) {
|
if (manifest.isFile() == false) {
|
||||||
errorAndExit("No AndroidManifest.xml file found in the main project directory: %1$s",
|
errorAndExit("No AndroidManifest.xml file found in the main project directory: %1$s",
|
||||||
parentProject.getAbsolutePath());
|
parentProject.getAbsolutePath());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now query the manifest for the package file.
|
// now query the manifest for the package file.
|
||||||
@@ -405,6 +417,7 @@ public class Main {
|
|||||||
String targetHash = p.getProperty(ProjectProperties.PROPERTY_TARGET);
|
String targetHash = p.getProperty(ProjectProperties.PROPERTY_TARGET);
|
||||||
if (targetHash == null) {
|
if (targetHash == null) {
|
||||||
errorAndExit("Couldn't find the main project target");
|
errorAndExit("Couldn't find the main project target");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and resolve it.
|
// and resolve it.
|
||||||
@@ -413,6 +426,7 @@ public class Main {
|
|||||||
errorAndExit(
|
errorAndExit(
|
||||||
"Unable to resolve main project target '%1$s'. You may want to install the platform in your SDK.",
|
"Unable to resolve main project target '%1$s'. You may want to install the platform in your SDK.",
|
||||||
targetHash);
|
targetHash);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mSdkLog.printf("Found main project target: %1$s\n", target.getFullName());
|
mSdkLog.printf("Found main project target: %1$s\n", target.getFullName());
|
||||||
|
|||||||
@@ -25,12 +25,23 @@ import com.android.sdklib.SdkManager;
|
|||||||
*/
|
*/
|
||||||
class SdkCommandLine extends CommandLineProcessor {
|
class SdkCommandLine extends CommandLineProcessor {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Steps needed to add a new action:
|
||||||
|
* - Each action is defined as a "verb object" followed by parameters.
|
||||||
|
* - Either reuse a VERB_ constant or define a new one.
|
||||||
|
* - Either reuse an OBJECT_ constant or define a new one.
|
||||||
|
* - Add a new entry to mAction with a one-line help summary.
|
||||||
|
* - In the constructor, add a define() call for each parameter (either mandatory
|
||||||
|
* or optional) for the given action.
|
||||||
|
*/
|
||||||
|
|
||||||
public final static String VERB_LIST = "list";
|
public final static String VERB_LIST = "list";
|
||||||
public final static String VERB_CREATE = "create";
|
public final static String VERB_CREATE = "create";
|
||||||
public final static String VERB_MOVE = "move";
|
public final static String VERB_MOVE = "move";
|
||||||
public final static String VERB_DELETE = "delete";
|
public final static String VERB_DELETE = "delete";
|
||||||
public final static String VERB_UPDATE = "update";
|
public final static String VERB_UPDATE = "update";
|
||||||
|
|
||||||
|
public static final String OBJECT_SDK = "sdk";
|
||||||
public static final String OBJECT_AVD = "avd";
|
public static final String OBJECT_AVD = "avd";
|
||||||
public static final String OBJECT_AVDS = "avds";
|
public static final String OBJECT_AVDS = "avds";
|
||||||
public static final String OBJECT_TARGET = "target";
|
public static final String OBJECT_TARGET = "target";
|
||||||
@@ -59,6 +70,10 @@ class SdkCommandLine extends CommandLineProcessor {
|
|||||||
/**
|
/**
|
||||||
* Action definitions for SdkManager command line.
|
* Action definitions for SdkManager command line.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
* This list serves two purposes: first it is used to know which verb/object
|
||||||
|
* actions are acceptable on the command-line; second it provides a summary
|
||||||
|
* for each action that is printed in the help.
|
||||||
|
* <p/>
|
||||||
* Each entry is a string array with:
|
* Each entry is a string array with:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li> the verb.
|
* <li> the verb.
|
||||||
@@ -98,11 +113,16 @@ class SdkCommandLine extends CommandLineProcessor {
|
|||||||
|
|
||||||
{ VERB_UPDATE, OBJECT_ADB,
|
{ VERB_UPDATE, OBJECT_ADB,
|
||||||
"Updates adb to support the USB devices declared in the SDK add-ons." },
|
"Updates adb to support the USB devices declared in the SDK add-ons." },
|
||||||
|
|
||||||
|
{ VERB_UPDATE, OBJECT_SDK,
|
||||||
|
"Updates the SDK by suggesting new platforms to install if available." }
|
||||||
};
|
};
|
||||||
|
|
||||||
public SdkCommandLine(ISdkLog logger) {
|
public SdkCommandLine(ISdkLog logger) {
|
||||||
super(logger, ACTIONS);
|
super(logger, ACTIONS);
|
||||||
|
|
||||||
|
// The following defines the parameters of the actions defined in mAction.
|
||||||
|
|
||||||
// --- create avd ---
|
// --- create avd ---
|
||||||
|
|
||||||
define(Mode.STRING, false,
|
define(Mode.STRING, false,
|
||||||
@@ -175,6 +195,7 @@ class SdkCommandLine extends CommandLineProcessor {
|
|||||||
"Project name", null);
|
"Project name", null);
|
||||||
|
|
||||||
// --- create test-project ---
|
// --- create test-project ---
|
||||||
|
|
||||||
define(Mode.STRING, true,
|
define(Mode.STRING, true,
|
||||||
VERB_CREATE, OBJECT_TEST_PROJECT,
|
VERB_CREATE, OBJECT_TEST_PROJECT,
|
||||||
"p", KEY_PATH,
|
"p", KEY_PATH,
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public class LocalPackagesPage extends Composite implements ISdkListener {
|
|||||||
mUpdateButton.addSelectionListener(new SelectionAdapter() {
|
mUpdateButton.addSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void widgetSelected(SelectionEvent e) {
|
public void widgetSelected(SelectionEvent e) {
|
||||||
onUpdateInstalledPackage(); //$hide$ (hide from SWT designer)
|
onUpdateSelected(); //$hide$ (hide from SWT designer)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ public class LocalPackagesPage extends Composite implements ISdkListener {
|
|||||||
mDescriptionLabel.setText(""); //$NON-NLS1-$
|
mDescriptionLabel.setText(""); //$NON-NLS1-$
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onUpdateInstalledPackage() {
|
private void onUpdateSelected() {
|
||||||
mUpdaterData.updateOrInstallAll(null /*selectedArchives*/);
|
mUpdaterData.updateOrInstallAll(null /*selectedArchives*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,12 +146,14 @@ class UpdaterData {
|
|||||||
return mSettingsController;
|
return mSettingsController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Adds a listener ({@link ISdkListener}) that is notified when the SDK is reloaded. */
|
||||||
public void addListeners(ISdkListener listener) {
|
public void addListeners(ISdkListener listener) {
|
||||||
if (mListeners.contains(listener) == false) {
|
if (mListeners.contains(listener) == false) {
|
||||||
mListeners.add(listener);
|
mListeners.add(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Removes a listener ({@link ISdkListener}) that is notified when the SDK is reloaded. */
|
||||||
public void removeListener(ISdkListener listener) {
|
public void removeListener(ISdkListener listener) {
|
||||||
mListeners.remove(listener);
|
mListeners.remove(listener);
|
||||||
}
|
}
|
||||||
@@ -444,9 +446,15 @@ class UpdaterData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to update all the *existing* local packages.
|
* Tries to update all the *existing* local packages.
|
||||||
* This first refreshes all sources, then compares the available remote packages with
|
* <p/>
|
||||||
* the current local ones and suggest updates to be done to the user. Finally all
|
* There are two modes of operation:
|
||||||
* selected updates are installed.
|
* <ul>
|
||||||
|
* <li>If selectedArchives is null, refreshes all sources, compares the available remote
|
||||||
|
* packages with the current local ones and suggest updates to be done to the user (including
|
||||||
|
* new platforms that the users doesn't have yet).
|
||||||
|
* <li>If selectedArchives is not null, this represents a list of archives/packages that
|
||||||
|
* the user wants to install or update, so just process these.
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param selectedArchives The list of remote archive to consider for the update.
|
* @param selectedArchives The list of remote archive to consider for the update.
|
||||||
* This can be null, in which case a list of remote archive is fetched from all
|
* This can be null, in which case a list of remote archive is fetched from all
|
||||||
@@ -463,6 +471,13 @@ class UpdaterData {
|
|||||||
getSources(),
|
getSources(),
|
||||||
getLocalSdkParser().getPackages());
|
getLocalSdkParser().getPackages());
|
||||||
|
|
||||||
|
if (selectedArchives == null) {
|
||||||
|
ul.addNewPlatforms(archives, getSources(), getLocalSdkParser().getPackages());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO if selectedArchives is null and archives.len==0, find if there's
|
||||||
|
// any new platform we can suggest to install instead.
|
||||||
|
|
||||||
UpdateChooserDialog dialog = new UpdateChooserDialog(getWindowShell(), this, archives);
|
UpdateChooserDialog dialog = new UpdateChooserDialog(getWindowShell(), this, archives);
|
||||||
dialog.open();
|
dialog.open();
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.sdkuilib.internal.repository;
|
|||||||
import com.android.sdklib.AndroidVersion;
|
import com.android.sdklib.AndroidVersion;
|
||||||
import com.android.sdklib.internal.repository.AddonPackage;
|
import com.android.sdklib.internal.repository.AddonPackage;
|
||||||
import com.android.sdklib.internal.repository.Archive;
|
import com.android.sdklib.internal.repository.Archive;
|
||||||
|
import com.android.sdklib.internal.repository.ExtraPackage;
|
||||||
import com.android.sdklib.internal.repository.MinToolsPackage;
|
import com.android.sdklib.internal.repository.MinToolsPackage;
|
||||||
import com.android.sdklib.internal.repository.Package;
|
import com.android.sdklib.internal.repository.Package;
|
||||||
import com.android.sdklib.internal.repository.PlatformPackage;
|
import com.android.sdklib.internal.repository.PlatformPackage;
|
||||||
@@ -29,6 +30,7 @@ import com.android.sdklib.internal.repository.Package.UpdateInfo;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logic to compute which packages to install, based on the choices
|
* The logic to compute which packages to install, based on the choices
|
||||||
@@ -39,8 +41,6 @@ import java.util.Collection;
|
|||||||
*/
|
*/
|
||||||
class UpdaterLogic {
|
class UpdaterLogic {
|
||||||
|
|
||||||
private RepoSources mSources;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute which packages to install by taking the user selection
|
* Compute which packages to install by taking the user selection
|
||||||
* and adding dependent packages as needed.
|
* and adding dependent packages as needed.
|
||||||
@@ -53,29 +53,127 @@ class UpdaterLogic {
|
|||||||
RepoSources sources,
|
RepoSources sources,
|
||||||
Package[] localPkgs) {
|
Package[] localPkgs) {
|
||||||
|
|
||||||
mSources = sources;
|
|
||||||
ArrayList<ArchiveInfo> archives = new ArrayList<ArchiveInfo>();
|
ArrayList<ArchiveInfo> archives = new ArrayList<ArchiveInfo>();
|
||||||
ArrayList<Package> remotePkgs = new ArrayList<Package>();
|
ArrayList<Package> remotePkgs = new ArrayList<Package>();
|
||||||
|
RepoSource[] remoteSources = sources.getSources();
|
||||||
|
|
||||||
if (selectedArchives == null) {
|
if (selectedArchives == null) {
|
||||||
selectedArchives = findUpdates(localPkgs, remotePkgs);
|
selectedArchives = findUpdates(localPkgs, remotePkgs, remoteSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Archive a : selectedArchives) {
|
for (Archive a : selectedArchives) {
|
||||||
insertArchive(a, archives, selectedArchives, remotePkgs, localPkgs, false);
|
insertArchive(a,
|
||||||
|
archives,
|
||||||
|
selectedArchives,
|
||||||
|
remotePkgs,
|
||||||
|
remoteSources,
|
||||||
|
localPkgs,
|
||||||
|
false /*automated*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
return archives;
|
return archives;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds new platforms that the user does not have in his/her local SDK
|
||||||
|
* and adds them to the list of archives to install.
|
||||||
|
*/
|
||||||
|
public void addNewPlatforms(ArrayList<ArchiveInfo> archives,
|
||||||
|
RepoSources sources,
|
||||||
|
Package[] localPkgs) {
|
||||||
|
// Find the highest platform installed
|
||||||
|
float currentPlatformScore = 0;
|
||||||
|
float currentAddonScore = 0;
|
||||||
|
HashMap<String, Float> currentExtraScore = new HashMap<String, Float>();
|
||||||
|
for (Package p : localPkgs) {
|
||||||
|
int rev = p.getRevision();
|
||||||
|
int api = 0;
|
||||||
|
boolean isPreview = false;
|
||||||
|
if (p instanceof PlatformPackage) {
|
||||||
|
AndroidVersion vers = ((PlatformPackage) p).getVersion();
|
||||||
|
api = vers.getApiLevel();
|
||||||
|
isPreview = vers.isPreview();
|
||||||
|
} else if (p instanceof AddonPackage) {
|
||||||
|
AndroidVersion vers = ((AddonPackage) p).getVersion();
|
||||||
|
api = vers.getApiLevel();
|
||||||
|
isPreview = vers.isPreview();
|
||||||
|
} else if (!(p instanceof ExtraPackage)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The score is 10*api + (1 if preview) + rev/100
|
||||||
|
// This allows previews to rank above a non-preview and
|
||||||
|
// allows revisions to rank appropriately.
|
||||||
|
float score = api * 10 + (isPreview ? 1 : 0) + rev/100.f;
|
||||||
|
|
||||||
|
if (p instanceof PlatformPackage) {
|
||||||
|
currentPlatformScore = Math.max(currentPlatformScore, score);
|
||||||
|
} else if (p instanceof AddonPackage) {
|
||||||
|
currentAddonScore = Math.max(currentAddonScore, score);
|
||||||
|
} else if (p instanceof ExtraPackage) {
|
||||||
|
currentExtraScore.put(((ExtraPackage) p).getPath(), score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RepoSource[] remoteSources = sources.getSources();
|
||||||
|
ArrayList<Package> remotePkgs = new ArrayList<Package>();
|
||||||
|
fetchRemotePackages(remotePkgs, remoteSources);
|
||||||
|
|
||||||
|
for (Package p : remotePkgs) {
|
||||||
|
int rev = p.getRevision();
|
||||||
|
int api = 0;
|
||||||
|
boolean isPreview = false;
|
||||||
|
if (p instanceof PlatformPackage) {
|
||||||
|
AndroidVersion vers = ((PlatformPackage) p).getVersion();
|
||||||
|
api = vers.getApiLevel();
|
||||||
|
isPreview = vers.isPreview();
|
||||||
|
} else if (p instanceof AddonPackage) {
|
||||||
|
AndroidVersion vers = ((AddonPackage) p).getVersion();
|
||||||
|
api = vers.getApiLevel();
|
||||||
|
isPreview = vers.isPreview();
|
||||||
|
} else if (!(p instanceof ExtraPackage)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float score = api * 10 + (isPreview ? 1 : 0) + rev/100.f;
|
||||||
|
|
||||||
|
boolean shouldAdd = false;
|
||||||
|
if (p instanceof PlatformPackage) {
|
||||||
|
shouldAdd = score > currentPlatformScore;
|
||||||
|
} else if (p instanceof AddonPackage) {
|
||||||
|
shouldAdd = score > currentAddonScore;
|
||||||
|
} else if (p instanceof ExtraPackage) {
|
||||||
|
String key = ((ExtraPackage) p).getPath();
|
||||||
|
shouldAdd = !currentExtraScore.containsKey(key) ||
|
||||||
|
score > currentExtraScore.get(key).floatValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldAdd) {
|
||||||
|
// We should suggest this package for installation.
|
||||||
|
for (Archive a : p.getArchives()) {
|
||||||
|
if (a.isCompatible()) {
|
||||||
|
insertArchive(a,
|
||||||
|
archives,
|
||||||
|
null /*selectedArchives*/,
|
||||||
|
remotePkgs,
|
||||||
|
remoteSources,
|
||||||
|
localPkgs,
|
||||||
|
true /*automated*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find suitable updates to all current local packages.
|
* Find suitable updates to all current local packages.
|
||||||
*/
|
*/
|
||||||
private Collection<Archive> findUpdates(Package[] localPkgs, ArrayList<Package> remotePkgs) {
|
private Collection<Archive> findUpdates(Package[] localPkgs,
|
||||||
|
ArrayList<Package> remotePkgs,
|
||||||
|
RepoSource[] remoteSources) {
|
||||||
ArrayList<Archive> updates = new ArrayList<Archive>();
|
ArrayList<Archive> updates = new ArrayList<Archive>();
|
||||||
|
|
||||||
fetchRemotePackages(remotePkgs);
|
fetchRemotePackages(remotePkgs, remoteSources);
|
||||||
|
|
||||||
for (Package localPkg : localPkgs) {
|
for (Package localPkg : localPkgs) {
|
||||||
for (Package remotePkg : remotePkgs) {
|
for (Package remotePkg : remotePkgs) {
|
||||||
@@ -100,6 +198,7 @@ class UpdaterLogic {
|
|||||||
ArrayList<ArchiveInfo> outArchives,
|
ArrayList<ArchiveInfo> outArchives,
|
||||||
Collection<Archive> selectedArchives,
|
Collection<Archive> selectedArchives,
|
||||||
ArrayList<Package> remotePkgs,
|
ArrayList<Package> remotePkgs,
|
||||||
|
RepoSource[] remoteSources,
|
||||||
Package[] localPkgs,
|
Package[] localPkgs,
|
||||||
boolean automated) {
|
boolean automated) {
|
||||||
Package p = archive.getParentPackage();
|
Package p = archive.getParentPackage();
|
||||||
@@ -114,15 +213,32 @@ class UpdaterLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find dependencies
|
// find dependencies
|
||||||
ArchiveInfo dep = findDependency(p, outArchives, selectedArchives, remotePkgs, localPkgs);
|
ArchiveInfo dep = findDependency(p,
|
||||||
|
outArchives,
|
||||||
|
selectedArchives,
|
||||||
|
remotePkgs,
|
||||||
|
remoteSources,
|
||||||
|
localPkgs);
|
||||||
|
|
||||||
ArchiveInfo ai = new ArchiveInfo(
|
// Make sure it's not a dup
|
||||||
|
ArchiveInfo ai = null;
|
||||||
|
|
||||||
|
for (ArchiveInfo ai2 : outArchives) {
|
||||||
|
if (ai2.getNewArchive().getParentPackage().sameItemAs(archive.getParentPackage())) {
|
||||||
|
ai = ai2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ai == null) {
|
||||||
|
ai = new ArchiveInfo(
|
||||||
archive, //newArchive
|
archive, //newArchive
|
||||||
updatedArchive, //replaced
|
updatedArchive, //replaced
|
||||||
dep //dependsOn
|
dep //dependsOn
|
||||||
);
|
);
|
||||||
|
|
||||||
outArchives.add(ai);
|
outArchives.add(ai);
|
||||||
|
}
|
||||||
|
|
||||||
if (dep != null) {
|
if (dep != null) {
|
||||||
dep.addDependencyFor(ai);
|
dep.addDependencyFor(ai);
|
||||||
}
|
}
|
||||||
@@ -134,6 +250,7 @@ class UpdaterLogic {
|
|||||||
ArrayList<ArchiveInfo> outArchives,
|
ArrayList<ArchiveInfo> outArchives,
|
||||||
Collection<Archive> selectedArchives,
|
Collection<Archive> selectedArchives,
|
||||||
ArrayList<Package> remotePkgs,
|
ArrayList<Package> remotePkgs,
|
||||||
|
RepoSource[] remoteSources,
|
||||||
Package[] localPkgs) {
|
Package[] localPkgs) {
|
||||||
|
|
||||||
// Current dependencies can be:
|
// Current dependencies can be:
|
||||||
@@ -144,13 +261,23 @@ class UpdaterLogic {
|
|||||||
AddonPackage addon = (AddonPackage) pkg;
|
AddonPackage addon = (AddonPackage) pkg;
|
||||||
|
|
||||||
return findPlatformDependency(
|
return findPlatformDependency(
|
||||||
addon, outArchives, selectedArchives, remotePkgs, localPkgs);
|
addon,
|
||||||
|
outArchives,
|
||||||
|
selectedArchives,
|
||||||
|
remotePkgs,
|
||||||
|
remoteSources,
|
||||||
|
localPkgs);
|
||||||
|
|
||||||
} else if (pkg instanceof MinToolsPackage) {
|
} else if (pkg instanceof MinToolsPackage) {
|
||||||
MinToolsPackage platformOrExtra = (MinToolsPackage) pkg;
|
MinToolsPackage platformOrExtra = (MinToolsPackage) pkg;
|
||||||
|
|
||||||
return findToolsDependency(
|
return findToolsDependency(
|
||||||
platformOrExtra, outArchives, selectedArchives, remotePkgs, localPkgs);
|
platformOrExtra,
|
||||||
|
outArchives,
|
||||||
|
selectedArchives,
|
||||||
|
remotePkgs,
|
||||||
|
remoteSources,
|
||||||
|
localPkgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -168,6 +295,7 @@ class UpdaterLogic {
|
|||||||
ArrayList<ArchiveInfo> outArchives,
|
ArrayList<ArchiveInfo> outArchives,
|
||||||
Collection<Archive> selectedArchives,
|
Collection<Archive> selectedArchives,
|
||||||
ArrayList<Package> remotePkgs,
|
ArrayList<Package> remotePkgs,
|
||||||
|
RepoSource[] remoteSources,
|
||||||
Package[] localPkgs) {
|
Package[] localPkgs) {
|
||||||
// This is the requirement to match.
|
// This is the requirement to match.
|
||||||
int rev = platformOrExtra.getMinToolsRevision();
|
int rev = platformOrExtra.getMinToolsRevision();
|
||||||
@@ -200,20 +328,22 @@ class UpdaterLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise look in the selected archives.
|
// Otherwise look in the selected archives.
|
||||||
|
if (selectedArchives != null) {
|
||||||
for (Archive a : selectedArchives) {
|
for (Archive a : selectedArchives) {
|
||||||
Package p = a.getParentPackage();
|
Package p = a.getParentPackage();
|
||||||
if (p instanceof ToolPackage) {
|
if (p instanceof ToolPackage) {
|
||||||
if (((ToolPackage) p).getRevision() >= rev) {
|
if (((ToolPackage) p).getRevision() >= rev) {
|
||||||
// It's not already in the list of things to install, so add it now
|
// It's not already in the list of things to install, so add it now
|
||||||
return insertArchive(a, outArchives,
|
return insertArchive(a, outArchives,
|
||||||
selectedArchives, remotePkgs, localPkgs,
|
selectedArchives, remotePkgs, remoteSources, localPkgs,
|
||||||
true);
|
true /*automated*/);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally nothing matched, so let's look at all available remote packages
|
// Finally nothing matched, so let's look at all available remote packages
|
||||||
fetchRemotePackages(remotePkgs);
|
fetchRemotePackages(remotePkgs, remoteSources);
|
||||||
for (Package p : remotePkgs) {
|
for (Package p : remotePkgs) {
|
||||||
if (p instanceof ToolPackage) {
|
if (p instanceof ToolPackage) {
|
||||||
if (((ToolPackage) p).getRevision() >= rev) {
|
if (((ToolPackage) p).getRevision() >= rev) {
|
||||||
@@ -222,8 +352,8 @@ class UpdaterLogic {
|
|||||||
for (Archive a : p.getArchives()) {
|
for (Archive a : p.getArchives()) {
|
||||||
if (a.isCompatible()) {
|
if (a.isCompatible()) {
|
||||||
return insertArchive(a, outArchives,
|
return insertArchive(a, outArchives,
|
||||||
selectedArchives, remotePkgs, localPkgs,
|
selectedArchives, remotePkgs, remoteSources, localPkgs,
|
||||||
true);
|
true /*automated*/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,6 +377,7 @@ class UpdaterLogic {
|
|||||||
ArrayList<ArchiveInfo> outArchives,
|
ArrayList<ArchiveInfo> outArchives,
|
||||||
Collection<Archive> selectedArchives,
|
Collection<Archive> selectedArchives,
|
||||||
ArrayList<Package> remotePkgs,
|
ArrayList<Package> remotePkgs,
|
||||||
|
RepoSource[] remoteSources,
|
||||||
Package[] localPkgs) {
|
Package[] localPkgs) {
|
||||||
// This is the requirement to match.
|
// This is the requirement to match.
|
||||||
AndroidVersion v = addon.getVersion();
|
AndroidVersion v = addon.getVersion();
|
||||||
@@ -276,20 +407,22 @@ class UpdaterLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise look in the selected archives.
|
// Otherwise look in the selected archives.
|
||||||
|
if (selectedArchives != null) {
|
||||||
for (Archive a : selectedArchives) {
|
for (Archive a : selectedArchives) {
|
||||||
Package p = a.getParentPackage();
|
Package p = a.getParentPackage();
|
||||||
if (p instanceof PlatformPackage) {
|
if (p instanceof PlatformPackage) {
|
||||||
if (v.equals(((PlatformPackage) p).getVersion())) {
|
if (v.equals(((PlatformPackage) p).getVersion())) {
|
||||||
// It's not already in the list of things to install, so add it now
|
// It's not already in the list of things to install, so add it now
|
||||||
return insertArchive(a, outArchives,
|
return insertArchive(a, outArchives,
|
||||||
selectedArchives, remotePkgs, localPkgs,
|
selectedArchives, remotePkgs, remoteSources, localPkgs,
|
||||||
true);
|
true /*automated*/);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally nothing matched, so let's look at all available remote packages
|
// Finally nothing matched, so let's look at all available remote packages
|
||||||
fetchRemotePackages(remotePkgs);
|
fetchRemotePackages(remotePkgs, remoteSources);
|
||||||
for (Package p : remotePkgs) {
|
for (Package p : remotePkgs) {
|
||||||
if (p instanceof PlatformPackage) {
|
if (p instanceof PlatformPackage) {
|
||||||
if (v.equals(((PlatformPackage) p).getVersion())) {
|
if (v.equals(((PlatformPackage) p).getVersion())) {
|
||||||
@@ -298,8 +431,8 @@ class UpdaterLogic {
|
|||||||
for (Archive a : p.getArchives()) {
|
for (Archive a : p.getArchives()) {
|
||||||
if (a.isCompatible()) {
|
if (a.isCompatible()) {
|
||||||
return insertArchive(a, outArchives,
|
return insertArchive(a, outArchives,
|
||||||
selectedArchives, remotePkgs, localPkgs,
|
selectedArchives, remotePkgs, remoteSources, localPkgs,
|
||||||
true);
|
true /*automated*/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,14 +448,11 @@ class UpdaterLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Fetch all remote packages only if really needed. */
|
/** Fetch all remote packages only if really needed. */
|
||||||
protected void fetchRemotePackages(ArrayList<Package> remotePkgs) {
|
protected void fetchRemotePackages(ArrayList<Package> remotePkgs, RepoSource[] remoteSources) {
|
||||||
if (remotePkgs.size() > 0) {
|
if (remotePkgs.size() > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all the available packages from all loaded sources
|
|
||||||
RepoSource[] remoteSources = mSources.getSources();
|
|
||||||
|
|
||||||
for (RepoSource remoteSrc : remoteSources) {
|
for (RepoSource remoteSrc : remoteSources) {
|
||||||
Package[] pkgs = remoteSrc.getPackages();
|
Package[] pkgs = remoteSrc.getPackages();
|
||||||
if (pkgs != null) {
|
if (pkgs != null) {
|
||||||
|
|||||||
@@ -60,7 +60,11 @@ public class UpdaterWindowImpl {
|
|||||||
private ArrayList<Object[]> mExtraPages;
|
private ArrayList<Object[]> mExtraPages;
|
||||||
/** A factory to create progress task dialogs. */
|
/** A factory to create progress task dialogs. */
|
||||||
private ProgressTaskFactory mTaskFactory;
|
private ProgressTaskFactory mTaskFactory;
|
||||||
|
/** The initial page to display. If null or not a know class, the first page will be displayed.
|
||||||
|
* Must be set before the first call to {@link #open()}. */
|
||||||
|
private Class<? extends Composite> mInitialPage;
|
||||||
|
/** Sets whether the auto-update wizard will be shown when opening the window. */
|
||||||
|
private boolean mRequestAutoUpdate;
|
||||||
|
|
||||||
// --- UI members ---
|
// --- UI members ---
|
||||||
|
|
||||||
@@ -148,7 +152,7 @@ public class UpdaterWindowImpl {
|
|||||||
// Hide everything down-below from SWT designer
|
// Hide everything down-below from SWT designer
|
||||||
//$hide>>$
|
//$hide>>$
|
||||||
|
|
||||||
// --- UI Callbacks -----------
|
// --- Public API -----------
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,14 +173,42 @@ public class UpdaterWindowImpl {
|
|||||||
mExtraPages.add(new Object[]{ title, pageClass });
|
mExtraPages.add(new Object[]{ title, pageClass });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate the initial page that should be selected when the window opens.
|
||||||
|
* This must be called before the call to {@link #open()}.
|
||||||
|
* If null or if the page class is not found, the first page will be selected.
|
||||||
|
*/
|
||||||
|
public void setInitialPage(Class<? extends Composite> pageClass) {
|
||||||
|
mInitialPage = pageClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the auto-update wizard will be shown when opening the window.
|
||||||
|
* <p/>
|
||||||
|
* This must be called before the call to {@link #open()}.
|
||||||
|
*/
|
||||||
|
public void setRequestAutoUpdate(boolean requestAutoUpdate) {
|
||||||
|
mRequestAutoUpdate = requestAutoUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new listener to be notified when a change is made to the content of the SDK.
|
||||||
|
*/
|
||||||
public void addListeners(ISdkListener listener) {
|
public void addListeners(ISdkListener listener) {
|
||||||
mUpdaterData.addListeners(listener);
|
mUpdaterData.addListeners(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a new listener to be notified anymore when a change is made to the content of
|
||||||
|
* the SDK.
|
||||||
|
*/
|
||||||
public void removeListener(ISdkListener listener) {
|
public void removeListener(ISdkListener listener) {
|
||||||
mUpdaterData.removeListener(listener);
|
mUpdaterData.removeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Internals & UI Callbacks -----------
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to return the SWT shell.
|
* Helper to return the SWT shell.
|
||||||
*/
|
*/
|
||||||
@@ -230,12 +262,25 @@ public class UpdaterWindowImpl {
|
|||||||
addPage(mRemotePackagesPage, "Available Packages");
|
addPage(mRemotePackagesPage, "Available Packages");
|
||||||
addExtraPages();
|
addExtraPages();
|
||||||
|
|
||||||
displayPage(0);
|
int pageIndex = 0;
|
||||||
mPageList.setSelection(0);
|
int i = 0;
|
||||||
|
for (Composite p : mPages) {
|
||||||
|
if (p.getClass().equals(mInitialPage)) {
|
||||||
|
pageIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
displayPage(pageIndex);
|
||||||
|
mPageList.setSelection(pageIndex);
|
||||||
|
|
||||||
setupSources();
|
setupSources();
|
||||||
initializeSettings();
|
initializeSettings();
|
||||||
mUpdaterData.notifyListeners();
|
mUpdaterData.notifyListeners();
|
||||||
|
|
||||||
|
if (mRequestAutoUpdate) {
|
||||||
|
mUpdaterData.updateOrInstallAll(null /*selectedArchives*/);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -69,6 +69,25 @@ public class UpdaterWindow {
|
|||||||
mWindow.registerExtraPage(title, pageClass);
|
mWindow.registerExtraPage(title, pageClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate the initial page that should be selected when the window opens.
|
||||||
|
* <p/>
|
||||||
|
* This must be called before the call to {@link #open()}.
|
||||||
|
* If null or if the page class is not found, the first page will be selected.
|
||||||
|
*/
|
||||||
|
public void setInitialPage(Class<? extends Composite> pageClass) {
|
||||||
|
mWindow.setInitialPage(pageClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the auto-update wizard will be shown when opening the window.
|
||||||
|
* <p/>
|
||||||
|
* This must be called before the call to {@link #open()}.
|
||||||
|
*/
|
||||||
|
public void setRequestAutoUpdate(boolean requestAutoUpdate) {
|
||||||
|
mWindow.setRequestAutoUpdate(requestAutoUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new listener to be notified when a change is made to the content of the SDK.
|
* Adds a new listener to be notified when a change is made to the content of the SDK.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.android.sdklib.internal.repository.MockAddonPackage;
|
|||||||
import com.android.sdklib.internal.repository.MockPlatformPackage;
|
import com.android.sdklib.internal.repository.MockPlatformPackage;
|
||||||
import com.android.sdklib.internal.repository.MockToolPackage;
|
import com.android.sdklib.internal.repository.MockToolPackage;
|
||||||
import com.android.sdklib.internal.repository.Package;
|
import com.android.sdklib.internal.repository.Package;
|
||||||
|
import com.android.sdklib.internal.repository.RepoSource;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -37,7 +38,10 @@ public class UpdaterLogicTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void fetchRemotePackages(ArrayList<Package> remotePkgs) {
|
protected void fetchRemotePackages(ArrayList<Package> remotePkgs,
|
||||||
|
RepoSource[] remoteSources) {
|
||||||
|
// Ignore remoteSources and instead uses the remotePackages list given to the
|
||||||
|
// constructor.
|
||||||
if (mRemotePackages != null) {
|
if (mRemotePackages != null) {
|
||||||
remotePkgs.addAll(Arrays.asList(mRemotePackages));
|
remotePkgs.addAll(Arrays.asList(mRemotePackages));
|
||||||
}
|
}
|
||||||
@@ -59,13 +63,14 @@ public class UpdaterLogicTest extends TestCase {
|
|||||||
|
|
||||||
// a2 depends on p2, which is not in the locals
|
// a2 depends on p2, which is not in the locals
|
||||||
Package[] locals = { p1, a1 };
|
Package[] locals = { p1, a1 };
|
||||||
assertNull(mul.findPlatformDependency(a2, out, selected, remote, locals));
|
RepoSource[] sources = null;
|
||||||
|
assertNull(mul.findPlatformDependency(a2, out, selected, remote, sources, locals));
|
||||||
assertEquals(0, out.size());
|
assertEquals(0, out.size());
|
||||||
|
|
||||||
// p2 is now selected, and should be scheduled for install in out
|
// p2 is now selected, and should be scheduled for install in out
|
||||||
Archive p2_archive = p2.getArchives()[0];
|
Archive p2_archive = p2.getArchives()[0];
|
||||||
selected.add(p2_archive);
|
selected.add(p2_archive);
|
||||||
ArchiveInfo ai2 = mul.findPlatformDependency(a2, out, selected, remote, locals);
|
ArchiveInfo ai2 = mul.findPlatformDependency(a2, out, selected, remote, sources, locals);
|
||||||
assertNotNull(ai2);
|
assertNotNull(ai2);
|
||||||
assertSame(p2_archive, ai2.getNewArchive());
|
assertSame(p2_archive, ai2.getNewArchive());
|
||||||
assertEquals(1, out.size());
|
assertEquals(1, out.size());
|
||||||
@@ -86,13 +91,14 @@ public class UpdaterLogicTest extends TestCase {
|
|||||||
|
|
||||||
// p2 depends on t2, which is not locally installed
|
// p2 depends on t2, which is not locally installed
|
||||||
Package[] locals = { t1 };
|
Package[] locals = { t1 };
|
||||||
assertNull(mul.findToolsDependency(p2, out, selected, remote, locals));
|
RepoSource[] sources = null;
|
||||||
|
assertNull(mul.findToolsDependency(p2, out, selected, remote, sources, locals));
|
||||||
assertEquals(0, out.size());
|
assertEquals(0, out.size());
|
||||||
|
|
||||||
// t2 is now selected and can be used as a dependency
|
// t2 is now selected and can be used as a dependency
|
||||||
Archive t2_archive = t2.getArchives()[0];
|
Archive t2_archive = t2.getArchives()[0];
|
||||||
selected.add(t2_archive);
|
selected.add(t2_archive);
|
||||||
ArchiveInfo ai2 = mul.findToolsDependency(p2, out, selected, remote, locals);
|
ArchiveInfo ai2 = mul.findToolsDependency(p2, out, selected, remote, sources, locals);
|
||||||
assertNotNull(ai2);
|
assertNotNull(ai2);
|
||||||
assertSame(t2_archive, ai2.getNewArchive());
|
assertSame(t2_archive, ai2.getNewArchive());
|
||||||
assertEquals(1, out.size());
|
assertEquals(1, out.size());
|
||||||
|
|||||||
Reference in New Issue
Block a user