blob: 96add711717ec7a637f4cafc78862d068cbbc0f2 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.eclipse.adt.internal.welcome;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.sdkstats.DdmsPreferenceStore;
import com.android.sdkstats.SdkStatsService;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import java.io.File;
/**
* ADT startup tasks (other than those performed in {@link AdtPlugin#start(org.osgi.framework.BundleContext)}
* when the plugin is initializing.
* <p>
* The main tasks currently performed are:
* <ul>
* <li> See if the user has ever run the welcome wizard, and if not, run it
* <li> Ping the usage statistics server, if enabled by the user. This is done here
* rather than during the plugin start since this task is run later (when the workspace
* is fully initialized) and we want to ask the user for permission for usage
* tracking before running it (and if we don't, then the usage tracking permissions
* dialog will run instead.)
* </ul>
*/
public class AdtStartup implements IStartup {
private DdmsPreferenceStore mStore = new DdmsPreferenceStore();
@Override
public void earlyStartup() {
if (isFirstTime()) {
showWelcomeWizard();
// Usage statistics are sent after the wizard has run asynchronously (provided the
// user opted in)
} else if (mStore.isPingOptIn()) {
sendUsageStats();
}
}
private boolean isFirstTime() {
// If we already have a known SDK location in our workspace then we know this
// is not the first time this user is running ADT.
String osSdkFolder = AdtPrefs.getPrefs().getOsSdkFolder();
if (osSdkFolder != null && osSdkFolder.length() > 0) {
return false;
}
// If we've recorded an SDK location in the .android settings, then the user
// has run ADT before but possibly in a different workspace. We don't want to pop up
// the welcome wizard each time if we can simply use the existing SDK install.
String osSdkPath = mStore.getLastSdkPath();
if (osSdkPath != null && osSdkPath.length() > 0 && new File(osSdkPath).isDirectory()) {
// Verify that the SDK is valid
boolean ok = AdtPlugin.getDefault().checkSdkLocationAndId(osSdkPath,
new AdtPlugin.CheckSdkErrorHandler() {
@Override
public boolean handleError(
CheckSdkErrorHandler.Solution solution,
String message) {
return false;
}
@Override
public boolean handleWarning(
CheckSdkErrorHandler.Solution solution,
String message) {
return true;
}
});
if (ok) {
// Yes, we've seen an SDK location before and we can use it again, no need to
// pester the user with the welcome wizard. (This also implies that the user
// has responded to the usage statistics question.)
AdtPrefs.getPrefs().setSdkLocation(new File(osSdkPath));
return false;
}
}
// Check whether we've run this wizard before.
return !mStore.isAdtUsed();
}
private void showWelcomeWizard() {
final IWorkbench workbench = PlatformUI.getWorkbench();
workbench.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
if (window != null) {
WelcomeWizard wizard = new WelcomeWizard(mStore);
WizardDialog dialog = new WizardDialog(window.getShell(), wizard);
dialog.open();
}
// Record the fact that we've run the wizard so we don't attempt to do it again,
// even if the user just cancels out of the wizard.
mStore.setAdtUsed(true);
if (mStore.isPingOptIn()) {
sendUsageStats();
}
}
});
}
private void sendUsageStats() {
// Ping the usage server and parse the SDK content.
// This is deferred in separate jobs to avoid blocking the bundle start.
// We also serialize them to avoid too many parallel jobs when Eclipse starts.
Job pingJob = createPingUsageServerJob();
// build jobs are run after other interactive jobs
pingJob.setPriority(Job.BUILD);
// Wait another 30 seconds before starting the ping job. This gives other
// startup tasks time to finish since it's not vital to get the usage ping
// immediately.
pingJob.schedule(30000 /*milliseconds*/);
}
/**
* Creates a job than can ping the usage server.
*/
private Job createPingUsageServerJob() {
// In order to not block the plugin loading, so we spawn another thread.
Job job = new Job("Android SDK Ping") { // Job name, visible in progress view
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
pingUsageServer();
return Status.OK_STATUS;
} catch (Throwable t) {
AdtPlugin.log(t, "pingUsageServer failed"); //$NON-NLS-1$
return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
"pingUsageServer failed", t); //$NON-NLS-1$
}
}
};
return job;
}
private static Version getVersion(Plugin plugin) {
@SuppressWarnings("cast") // Cast required in Eclipse 3.5; prevent auto-removal in 3.7
String version = (String) plugin.getBundle().getHeaders().get(Constants.BUNDLE_VERSION);
// Parse the string using the Version class.
return new Version(version);
}
/**
* Pings the usage start server.
*/
private void pingUsageServer() {
// Report the version of the ADT plugin to the stat server
Version version = getVersion(AdtPlugin.getDefault());
String adtVersionString = String.format("%1$d.%2$d.%3$d", version.getMajor(), //$NON-NLS-1$
version.getMinor(), version.getMicro());
// Report the version of Eclipse to the stat server.
// Get the version of eclipse by getting the version of one of the runtime plugins.
Version eclipseVersion = getVersion(ResourcesPlugin.getPlugin());
String eclipseVersionString = String.format("%1$d.%2$d", //$NON-NLS-1$
eclipseVersion.getMajor(), eclipseVersion.getMinor());
SdkStatsService stats = new SdkStatsService();
stats.ping("adt", adtVersionString); //$NON-NLS-1$
stats.ping("eclipse", eclipseVersionString); //$NON-NLS-1$
}
}