aboutsummaryrefslogtreecommitdiffstats
path: root/sdkmanager
diff options
context:
space:
mode:
Diffstat (limited to 'sdkmanager')
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DownloadCache.java15
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java14
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java132
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java6
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackageLoader.java138
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java6
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java58
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java7
8 files changed, 245 insertions, 131 deletions
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DownloadCache.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DownloadCache.java
index c29e988..591e447 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DownloadCache.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DownloadCache.java
@@ -134,6 +134,12 @@ public class DownloadCache {
public enum Strategy {
/**
+ * Exclusively serves data from the cache. If files are available in the
+ * cache, serve them as is (without trying to refresh them). If files are
+ * not available, they are <em>not</em> fetched at all.
+ */
+ ONLY_CACHE,
+ /**
* If the files are available in the cache, serve them as-is, otherwise
* download them and return the cached version. No expiration or refresh
* is attempted if a file is in the cache.
@@ -237,6 +243,7 @@ public class DownloadCache {
* @param monitor {@link ITaskMonitor} which is related to this URL
* fetching.
* @return Returns an {@link InputStream} holding the URL content.
+ * Returns null if the document is not cached and strategy is {@link Strategy#ONLY_CACHE}.
* @throws IOException Exception thrown when there are problems retrieving
* the URL or its content.
* @throws CanceledByUserException Exception thrown if the user cancels the
@@ -414,6 +421,14 @@ public class DownloadCache {
} catch (IOException ignore) {}
}
+ if (!useCached && mStrategy == Strategy.ONLY_CACHE) {
+ // We don't have a document to serve from the cache.
+ if (DEBUG) {
+ System.out.println(String.format("%s : file not in cache", urlString)); //$NON-NLS-1$
+ }
+ return null;
+ }
+
// If we're not using the cache, try to remove the cache and download again.
try {
cached.delete();
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java
index fb59b42..dfd197d 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java
@@ -16,6 +16,7 @@
package com.android.sdklib.internal.repository;
+
/**
* A factory that can start and run new {@link ITask}s.
*/
@@ -23,6 +24,12 @@ public interface ITaskFactory {
/**
* Starts a new task with a new {@link ITaskMonitor}.
+ * <p/>
+ * The task will execute in a thread and runs it own UI loop.
+ * This means the task can perform UI operations using
+ * {@code Display#asyncExec(Runnable)}.
+ * <p/>
+ * In either case, the method only returns when the task has finished.
*
* @param title The title of the task, displayed in the monitor if any.
* @param task The task to run.
@@ -36,6 +43,13 @@ public interface ITaskFactory {
* and give the sub-monitor to the new task with the number of work units you want
* it to fill. The {@link #start} method will make sure to <em>fill</em> the progress
* when the task is completed, in case the actual task did not.
+ * <p/>
+ * When a task is started from within a monitor, it reuses the thread
+ * from the parent. Otherwise it starts a new thread and runs it own
+ * UI loop. This means the task can perform UI operations using
+ * {@code Display#asyncExec(Runnable)}.
+ * <p/>
+ * In either case, the method only returns when the task has finished.
*
* @param title The title of the task, displayed in the monitor if any.
* @param parentMonitor The parent monitor. Can be null.
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 a58e0f0..af40d78 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
@@ -24,31 +24,28 @@ import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.repository.AdbWrapper;
-import com.android.sdklib.internal.repository.AddonsListFetcher;
-import com.android.sdklib.internal.repository.AddonsListFetcher.Site;
+import com.android.sdklib.internal.repository.DownloadCache;
+import com.android.sdklib.internal.repository.ITask;
+import com.android.sdklib.internal.repository.ITaskFactory;
+import com.android.sdklib.internal.repository.ITaskMonitor;
+import com.android.sdklib.internal.repository.LocalSdkParser;
+import com.android.sdklib.internal.repository.NullTaskMonitor;
import com.android.sdklib.internal.repository.archives.Archive;
import com.android.sdklib.internal.repository.archives.ArchiveInstaller;
import com.android.sdklib.internal.repository.packages.AddonPackage;
import com.android.sdklib.internal.repository.packages.Package;
import com.android.sdklib.internal.repository.packages.PlatformToolPackage;
import com.android.sdklib.internal.repository.packages.ToolPackage;
-import com.android.sdklib.internal.repository.sources.SdkAddonSource;
import com.android.sdklib.internal.repository.sources.SdkRepoSource;
import com.android.sdklib.internal.repository.sources.SdkSource;
import com.android.sdklib.internal.repository.sources.SdkSourceCategory;
import com.android.sdklib.internal.repository.sources.SdkSources;
-import com.android.sdklib.internal.repository.DownloadCache;
-import com.android.sdklib.internal.repository.ITask;
-import com.android.sdklib.internal.repository.ITaskFactory;
-import com.android.sdklib.internal.repository.ITaskMonitor;
-import com.android.sdklib.internal.repository.LocalSdkParser;
-import com.android.sdklib.internal.repository.NullTaskMonitor;
import com.android.sdklib.repository.SdkAddonConstants;
-import com.android.sdklib.repository.SdkAddonsListConstants;
import com.android.sdklib.repository.SdkRepoConstants;
import com.android.sdklib.util.LineUtil;
import com.android.sdklib.util.SparseIntArray;
import com.android.sdkuilib.internal.repository.icons.ImageFactory;
+import com.android.sdkuilib.internal.repository.sdkman2.PackageLoader;
import com.android.sdkuilib.internal.repository.sdkman2.SdkUpdaterWindowImpl2;
import com.android.sdkuilib.repository.ISdkChangeListener;
@@ -79,27 +76,32 @@ public class UpdaterData implements IUpdaterData {
private String mOsSdkRoot;
- private final ISdkLog mSdkLog;
- private ITaskFactory mTaskFactory;
-
- private SdkManager mSdkManager;
- private AvdManager mAvdManager;
- private DownloadCache mDownloadCache; // lazily created in getDownloadCache
private final LocalSdkParser mLocalSdkParser = new LocalSdkParser();
private final SdkSources mSources = new SdkSources();
- private ImageFactory mImageFactory;
private final SettingsController mSettingsController;
private final ArrayList<ISdkChangeListener> mListeners = new ArrayList<ISdkChangeListener>();
+ private final ISdkLog mSdkLog;
+ private ITaskFactory mTaskFactory;
private Shell mWindowShell;
- private AndroidLocationException mAvdManagerInitError;
-
+ private SdkManager mSdkManager;
+ private AvdManager mAvdManager;
/**
- * 0 = need to fetch remote addons list once..
- * 1 = fetch succeeded, don't need to do it any more.
- * -1= fetch failed, do it again only if the user requests a refresh
- * or changes the force-http setting.
+ * The current {@link PackageLoader} to use.
+ * Lazily created in {@link #getPackageLoader()}.
*/
- private int mStateFetchRemoteAddonsList;
+ private PackageLoader mPackageLoader;
+ /**
+ * The current {@link DownloadCache} to use.
+ * Lazily created in {@link #getDownloadCache()}.
+ */
+ private DownloadCache mDownloadCache;
+ /**
+ * The current {@link ImageFactory}.
+ * Set via {@link #setImageFactory(ImageFactory)} by the window implementation.
+ * It is null when invoked using the command-line interface.
+ */
+ private ImageFactory mImageFactory;
+ private AndroidLocationException mAvdManagerInitError;
/**
* Creates a new updater data.
@@ -111,7 +113,6 @@ public class UpdaterData implements IUpdaterData {
mOsSdkRoot = osSdkRoot;
mSdkLog = sdkLog;
- mDownloadCache = getDownloadCache();
mSettingsController = new SettingsController(this);
initSdk();
@@ -198,6 +199,14 @@ public class UpdaterData implements IUpdaterData {
return mWindowShell;
}
+ public PackageLoader getPackageLoader() {
+ // The package loader is lazily initialized here.
+ if (mPackageLoader == null) {
+ mPackageLoader = new PackageLoader(this);
+ }
+ return mPackageLoader;
+ }
+
/**
* Check if any error occurred during initialization.
* If it did, display an error message.
@@ -446,7 +455,7 @@ public class UpdaterData implements IUpdaterData {
mOsSdkRoot,
forceHttp,
mSdkManager,
- mDownloadCache,
+ getDownloadCache(),
monitor)) {
// We installed this archive.
newlyInstalledArchives.add(archive);
@@ -698,7 +707,7 @@ public class UpdaterData implements IUpdaterData {
includeObsoletes);
if (selectedArchives == null) {
- loadRemoteAddonsList(new NullTaskMonitor(getSdkLog()));
+ getPackageLoader().loadRemoteAddonsList(new NullTaskMonitor(getSdkLog()));
ul.addNewPlatforms(
archives,
getSources(),
@@ -733,7 +742,7 @@ public class UpdaterData implements IUpdaterData {
*/
private List<ArchiveInfo> getRemoteArchives_NoGUI(boolean includeAll) {
refreshSources(true);
- loadRemoteAddonsList(new NullTaskMonitor(getSdkLog()));
+ getPackageLoader().loadRemoteAddonsList(new NullTaskMonitor(getSdkLog()));
List<ArchiveInfo> archives;
SdkUpdaterLogic ul = new SdkUpdaterLogic(this);
@@ -998,9 +1007,7 @@ public class UpdaterData implements IUpdaterData {
@Override
public void run(ITaskMonitor monitor) {
- if (mStateFetchRemoteAddonsList <= 0) {
- loadRemoteAddonsListInTask(monitor);
- }
+ getPackageLoader().loadRemoteAddonsList(monitor);
SdkSource[] sources = mSources.getAllSources();
monitor.setDescription("Refresh Sources");
@@ -1009,7 +1016,7 @@ public class UpdaterData implements IUpdaterData {
if (forceFetching ||
source.getPackages() != null ||
source.getFetchError() != null) {
- source.load(mDownloadCache, monitor.createSubMonitor(1), forceHttp);
+ source.load(getDownloadCache(), monitor.createSubMonitor(1), forceHttp);
}
monitor.incProgress(1);
}
@@ -1018,67 +1025,6 @@ public class UpdaterData implements IUpdaterData {
}
/**
- * Loads the remote add-ons list.
- */
- public void loadRemoteAddonsList(ITaskMonitor monitor) {
-
- if (mStateFetchRemoteAddonsList != 0) {
- return;
- }
-
- mTaskFactory.start("Load Add-ons List", monitor, new ITask() {
- @Override
- public void run(ITaskMonitor subMonitor) {
- loadRemoteAddonsListInTask(subMonitor);
- }
- });
- }
-
- private void loadRemoteAddonsListInTask(ITaskMonitor monitor) {
- mStateFetchRemoteAddonsList = -1;
-
- String url = SdkAddonsListConstants.URL_ADDON_LIST;
-
- // We override SdkRepoConstants.URL_GOOGLE_SDK_SITE if this is defined
- String baseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$
- if (baseUrl != null) {
- if (baseUrl.length() > 0 && baseUrl.endsWith("/")) { //$NON-NLS-1$
- if (url.startsWith(SdkRepoConstants.URL_GOOGLE_SDK_SITE)) {
- url = baseUrl + url.substring(SdkRepoConstants.URL_GOOGLE_SDK_SITE.length());
- }
- } else {
- monitor.logError("Ignoring invalid SDK_TEST_BASE_URL: %1$s", baseUrl); //$NON-NLS-1$
- }
- }
-
- if (getSettingsController().getForceHttp()) {
- url = url.replaceAll("https://", "http://"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- // Hook to bypass loading 3rd party addons lists.
- boolean fetch3rdParties = System.getenv("SDK_SKIP_3RD_PARTIES") == null;
-
- AddonsListFetcher fetcher = new AddonsListFetcher();
- Site[] sites = fetcher.fetch(url, mDownloadCache, monitor);
- if (sites != null) {
- mSources.removeAll(SdkSourceCategory.ADDONS_3RD_PARTY);
-
- if (fetch3rdParties) {
- for (Site s : sites) {
- mSources.add(SdkSourceCategory.ADDONS_3RD_PARTY,
- new SdkAddonSource(s.getUrl(), s.getUiName()));
- }
- }
-
- mSources.notifyChangeListeners();
-
- mStateFetchRemoteAddonsList = 1;
- }
-
- monitor.setDescription("Fetched Add-ons List successfully");
- }
-
- /**
* Safely invoke all the registered {@link ISdkChangeListener#onSdkLoaded()}.
* This can be called from any thread.
*/
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
index f481b0a..ba9bce7 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
@@ -76,7 +76,7 @@ public class AdtUpdateDialog extends SwtBaseDialog {
private Map<Package, File> mResultPaths = null;
private SettingsController mSettingsController;
private PackageFilter mPackageFilter;
- private PackageLoader mPackageMananger;
+ private PackageLoader mPackageLoader;
private ProgressBar mProgressBar;
private Label mStatusText;
@@ -221,12 +221,12 @@ public class AdtUpdateDialog extends SwtBaseDialog {
mUpdaterData.broadcastOnSdkLoaded();
- mPackageMananger = new PackageLoader(mUpdaterData);
+ mPackageLoader = new PackageLoader(mUpdaterData);
}
@Override
protected void eventLoop() {
- mPackageMananger.loadPackagesWithInstallTask(
+ mPackageLoader.loadPackagesWithInstallTask(
mPackageFilter.installFlags(),
new IAutoInstallTask() {
@Override
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackageLoader.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackageLoader.java
index 4ac03e9..ecbefb7 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackageLoader.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackageLoader.java
@@ -16,6 +16,8 @@
package com.android.sdkuilib.internal.repository.sdkman2;
+import com.android.sdklib.internal.repository.AddonsListFetcher;
+import com.android.sdklib.internal.repository.AddonsListFetcher.Site;
import com.android.sdklib.internal.repository.DownloadCache;
import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor;
@@ -23,7 +25,12 @@ import com.android.sdklib.internal.repository.NullTaskMonitor;
import com.android.sdklib.internal.repository.archives.Archive;
import com.android.sdklib.internal.repository.packages.Package;
import com.android.sdklib.internal.repository.packages.Package.UpdateInfo;
+import com.android.sdklib.internal.repository.sources.SdkAddonSource;
import com.android.sdklib.internal.repository.sources.SdkSource;
+import com.android.sdklib.internal.repository.sources.SdkSourceCategory;
+import com.android.sdklib.internal.repository.sources.SdkSources;
+import com.android.sdklib.repository.SdkAddonsListConstants;
+import com.android.sdklib.repository.SdkRepoConstants;
import com.android.sdkuilib.internal.repository.UpdaterData;
import org.eclipse.swt.widgets.Display;
@@ -39,13 +46,30 @@ import java.util.Map;
* Loads packages fetched from the remote SDK Repository and keeps track
* of their state compared with the current local SDK installation.
*/
-class PackageLoader {
+public class PackageLoader {
+ /** The update data context. Never null. */
private final UpdaterData mUpdaterData;
/**
+ * The {@link DownloadCache} override. Can be null, in which case the one from
+ * {@link UpdaterData} is used instead.
+ * @see #getDownloadCache()
+ */
+ private final DownloadCache mOverrideCache;
+
+ /**
+ * 0 = need to fetch remote addons list once..
+ * 1 = fetch succeeded, don't need to do it any more.
+ * -1= fetch failed, do it again only if the user requests a refresh
+ * or changes the force-http setting.
+ */
+ private int mStateFetchRemoteAddonsList;
+
+
+ /**
* Interface for the callback called by
- * {@link PackageLoader#loadPackages(DownloadCache, ISourceLoadedCallback)}.
+ * {@link PackageLoader#loadPackages(ISourceLoadedCallback)}.
* <p/>
* After processing each source, the package loader calls {@link #onUpdateSource}
* with the list of packages found in that source.
@@ -128,12 +152,27 @@ class PackageLoader {
}
/**
- * Creates a new PackageManager associated with the given {@link UpdaterData}.
+ * Creates a new PackageManager associated with the given {@link UpdaterData}
+ * and using the {@link UpdaterData}'s default {@link DownloadCache}.
*
* @param updaterData The {@link UpdaterData}. Must not be null.
*/
public PackageLoader(UpdaterData updaterData) {
mUpdaterData = updaterData;
+ mOverrideCache = null;
+ }
+
+ /**
+ * Creates a new PackageManager associated with the given {@link UpdaterData}
+ * but using the specified {@link DownloadCache} instead of the one from
+ * {@link UpdaterData}.
+ *
+ * @param updaterData The {@link UpdaterData}. Must not be null.
+ * @param cache The {@link DownloadCache} to use instead of the one from {@link UpdaterData}.
+ */
+ public PackageLoader(UpdaterData updaterData, DownloadCache cache) {
+ mUpdaterData = updaterData;
+ mOverrideCache = cache;
}
/**
@@ -145,20 +184,12 @@ class PackageLoader {
* after each source is finished loaded. In return the callback tells the loader
* whether to continue loading sources.
*/
- public void loadPackages(
- DownloadCache downloadCache,
- final ISourceLoadedCallback sourceLoadedCallback) {
+ public void loadPackages(final ISourceLoadedCallback sourceLoadedCallback) {
try {
if (mUpdaterData == null) {
return;
}
- if (downloadCache == null) {
- downloadCache = mUpdaterData.getDownloadCache();
- }
-
- final DownloadCache downloadCache2 = downloadCache;
-
mUpdaterData.getTaskFactory().start("Loading Sources", new ITask() {
@Override
public void run(ITaskMonitor monitor) {
@@ -176,7 +207,7 @@ class PackageLoader {
// get remote packages
boolean forceHttp = mUpdaterData.getSettingsController().getForceHttp();
- mUpdaterData.loadRemoteAddonsList(monitor.createSubMonitor(1));
+ loadRemoteAddonsList(monitor.createSubMonitor(1));
SdkSource[] sources = mUpdaterData.getSources().getAllSources();
try {
@@ -186,7 +217,7 @@ class PackageLoader {
for (SdkSource source : sources) {
Package[] pkgs = source.getPackages();
if (pkgs == null) {
- source.load(downloadCache2,
+ source.load(getDownloadCache(),
subMonitor.createSubMonitor(1),
forceHttp);
pkgs = source.getPackages();
@@ -215,8 +246,7 @@ class PackageLoader {
}
/**
- * Load packages, source by source using
- * {@link #loadPackages(DownloadCache, ISourceLoadedCallback)},
+ * Load packages, source by source using {@link #loadPackages(ISourceLoadedCallback)},
* and executes the given {@link IAutoInstallTask} on the current package list.
* That is for each package known, the install task is queried to find if
* the package is the one to be installed or updated.
@@ -248,8 +278,7 @@ class PackageLoader {
final int installFlags,
final IAutoInstallTask installTask) {
- loadPackages(mUpdaterData.getDownloadCache(),
- new ISourceLoadedCallback() {
+ loadPackages(new ISourceLoadedCallback() {
List<Archive> mArchivesToInstall = new ArrayList<Archive>();
Map<Package, File> mInstallPaths = new HashMap<Package, File>();
@@ -367,4 +396,77 @@ class PackageLoader {
}
});
}
+
+
+ /**
+ * Loads the remote add-ons list.
+ */
+ public void loadRemoteAddonsList(ITaskMonitor monitor) {
+
+ if (mStateFetchRemoteAddonsList != 0) {
+ return;
+ }
+
+ mUpdaterData.getTaskFactory().start("Load Add-ons List", monitor, new ITask() {
+ @Override
+ public void run(ITaskMonitor subMonitor) {
+ loadRemoteAddonsListInTask(subMonitor);
+ }
+ });
+ }
+
+ private void loadRemoteAddonsListInTask(ITaskMonitor monitor) {
+ mStateFetchRemoteAddonsList = -1;
+
+ String url = SdkAddonsListConstants.URL_ADDON_LIST;
+
+ // We override SdkRepoConstants.URL_GOOGLE_SDK_SITE if this is defined
+ String baseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$
+ if (baseUrl != null) {
+ if (baseUrl.length() > 0 && baseUrl.endsWith("/")) { //$NON-NLS-1$
+ if (url.startsWith(SdkRepoConstants.URL_GOOGLE_SDK_SITE)) {
+ url = baseUrl + url.substring(SdkRepoConstants.URL_GOOGLE_SDK_SITE.length());
+ }
+ } else {
+ monitor.logError("Ignoring invalid SDK_TEST_BASE_URL: %1$s", baseUrl); //$NON-NLS-1$
+ }
+ }
+
+ if (mUpdaterData.getSettingsController().getForceHttp()) {
+ url = url.replaceAll("https://", "http://"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // Hook to bypass loading 3rd party addons lists.
+ boolean fetch3rdParties = System.getenv("SDK_SKIP_3RD_PARTIES") == null;
+
+ AddonsListFetcher fetcher = new AddonsListFetcher();
+ Site[] sites = fetcher.fetch(url, getDownloadCache(), monitor);
+ if (sites != null) {
+ SdkSources sources = mUpdaterData.getSources();
+ sources.removeAll(SdkSourceCategory.ADDONS_3RD_PARTY);
+
+ if (fetch3rdParties) {
+ for (Site s : sites) {
+ sources.add(SdkSourceCategory.ADDONS_3RD_PARTY,
+ new SdkAddonSource(s.getUrl(), s.getUiName()));
+ }
+ }
+
+ sources.notifyChangeListeners();
+
+ mStateFetchRemoteAddonsList = 1;
+ }
+
+ monitor.setDescription("Fetched Add-ons List successfully");
+ }
+
+ /**
+ * Returns the {@link DownloadCache} to use.
+ *
+ * @return Returns {@link #mOverrideCache} if not null; otherwise returns the
+ * one from {@link UpdaterData} is used instead.
+ */
+ private DownloadCache getDownloadCache() {
+ return mOverrideCache != null ? mOverrideCache : mUpdaterData.getDownloadCache();
+ }
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java
index 8e1cbb3..9e45748 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java
@@ -48,17 +48,11 @@ import java.util.Set;
* so that we can test it using head-less unit tests.
*/
class PackagesDiffLogic {
- private final PackageLoader mPackageLoader;
private final UpdaterData mUpdaterData;
private boolean mFirstLoadComplete = true;
public PackagesDiffLogic(UpdaterData updaterData) {
mUpdaterData = updaterData;
- mPackageLoader = new PackageLoader(updaterData);
- }
-
- public PackageLoader getPackageLoader() {
- return mPackageLoader;
}
/**
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java
index 51543e8..40a3538 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java
@@ -17,6 +17,8 @@
package com.android.sdkuilib.internal.repository.sdkman2;
import com.android.sdklib.SdkConstants;
+import com.android.sdklib.internal.repository.DownloadCache;
+import com.android.sdklib.internal.repository.DownloadCache.Strategy;
import com.android.sdklib.internal.repository.IDescription;
import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor;
@@ -129,6 +131,7 @@ public class PackagesPage extends UpdaterPage implements ISdkChangeListener {
private final SdkInvocationContext mContext;
private final UpdaterData mUpdaterData;
private final PackagesDiffLogic mDiffLogic;
+
private boolean mDisplayArchives = false;
private boolean mOperationPending;
@@ -168,8 +171,15 @@ public class PackagesPage extends UpdaterPage implements ISdkChangeListener {
}
public void performFirstLoad() {
- // Initialize the package list the first time the page is shown.
- loadPackages(true /*isFirstLoad*/);
+ // First a package loader is created that only checks
+ // the local cache xml files. It populates the package
+ // list based on what the client got last, essentially.
+ loadPackages(true /*useLocalCache*/);
+
+ // Next a regular package loader is created that will
+ // respect the expiration and refresh parameters of the
+ // download cache.
+ loadPackages(false /*useLocalCache*/);
}
@SuppressWarnings("unused")
@@ -576,11 +586,24 @@ public class PackagesPage extends UpdaterPage implements ISdkChangeListener {
loadPackages();
}
+ /**
+ * Performs a "normal" reload of the package information, use the default download
+ * cache and refreshing strategy as needed.
+ */
private void loadPackages() {
- loadPackages(false /*isFirstLoad*/);
+ loadPackages(false /*useLocalCache*/);
}
- private void loadPackages(final boolean isFirstLoad) {
+ /**
+ * Performs a reload of the package information.
+ *
+ * @param useLocalCache When true, the {@link PackageLoader} is switched to use
+ * a specific {@link DownloadCache} using the {@link Strategy#ONLY_CACHE}, meaning
+ * it will only use data from the local cache. It will not try to fetch or refresh
+ * manifests. This is used once the very first time the sdk manager window opens
+ * and is typically followed by a regular load with refresh.
+ */
+ private void loadPackages(final boolean useLocalCache) {
if (mUpdaterData == null) {
return;
}
@@ -593,15 +616,26 @@ public class PackagesPage extends UpdaterPage implements ISdkChangeListener {
final boolean displaySortByApi = isSortByApi();
- if (!mTreeColumnName.isDisposed()) {
- mTreeColumnName.setImage(
- getImage(displaySortByApi ? ICON_SORT_BY_API : ICON_SORT_BY_SOURCE));
+ if (mTreeColumnName.isDisposed()) {
+ // If the UI got disposed, don't try to load anything since we won't be
+ // able to display it anyway.
+ return;
+ }
+
+ mTreeColumnName.setImage(getImage(displaySortByApi ? ICON_SORT_BY_API
+ : ICON_SORT_BY_SOURCE));
+
+ PackageLoader packageLoader = null;
+ if (useLocalCache) {
+ packageLoader =
+ new PackageLoader(mUpdaterData, new DownloadCache(Strategy.ONLY_CACHE));
+ } else {
+ packageLoader = mUpdaterData.getPackageLoader();
}
+ assert packageLoader != null;
mDiffLogic.updateStart();
- mDiffLogic.getPackageLoader().loadPackages(
- mUpdaterData.getDownloadCache(), // TODO do a first pass with Cache=SERVE_CACHE
- new ISourceLoadedCallback() {
+ packageLoader.loadPackages(new ISourceLoadedCallback() {
@Override
public boolean onUpdateSource(SdkSource source, Package[] newPackages) {
// This runs in a thread and must not access UI directly.
@@ -640,7 +674,9 @@ public class PackagesPage extends UpdaterPage implements ISdkChangeListener {
refreshViewerInput();
}
- if (mDiffLogic.isFirstLoadComplete() && !mGroupPackages.isDisposed()) {
+ if (!useLocalCache &&
+ mDiffLogic.isFirstLoadComplete() &&
+ !mGroupPackages.isDisposed()) {
// At the end of the first load, if nothing is selected then
// automatically select all new and update packages.
Object[] checked = mTreeViewer.getCheckedElements();
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java
index 8444f9f..3448852 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java
@@ -100,6 +100,13 @@ public final class ProgressView implements IProgressUiProvider {
/**
* Starts the task and block till it's either finished or canceled.
* This can be called from a non-UI thread safely.
+ * <p/>
+ * When a task is started from within a monitor, it reuses the thread
+ * from the parent. Otherwise it starts a new thread and runs it own
+ * UI loop. This means the task can perform UI operations using
+ * {@link Display#asyncExec(Runnable)}.
+ * <p/>
+ * In either case, the method only returns when the task has finished.
*/
public void startTask(
final String title,