aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizard.java
blob: 916924e99a179f8546f4933993106eafe50586bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * 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.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog;
import com.android.sdkstats.DdmsPreferenceStore;
import com.android.sdkuilib.internal.repository.ui.AdtUpdateDialog;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

/**
 * Wizard shown on first start for new users: configure SDK location, accept or
 * reject usage data collection, etc
 */
public class WelcomeWizard extends Wizard {
    private final DdmsPreferenceStore mStore;

    private WelcomeWizardPage mWelcomePage;
    private UsagePermissionPage mUsagePage;

    private final boolean mShowWelcomePage;
    private final boolean mShowUsagePage;

    /**
     * Creates a new {@link WelcomeWizard}
     *
     * @param store preferences for usage statistics collection etc
     * @param showInstallSdkPage show page to install SDK's
     * @param showUsageOptinPage show page to get user consent for usage data collection
     */
    public WelcomeWizard(DdmsPreferenceStore store, boolean showInstallSdkPage,
            boolean showUsageOptinPage) {
        mStore = store;
        mShowWelcomePage = showInstallSdkPage;
        mShowUsagePage = showUsageOptinPage;

        setWindowTitle("Welcome to Android Development");
        ImageDescriptor image = AdtPlugin.getImageDescriptor("icons/android-64.png"); //$NON-NLS-1$
        setDefaultPageImageDescriptor(image);
    }

    @Override
    public void addPages() {
        if (mShowWelcomePage) {
            mWelcomePage = new WelcomeWizardPage();
            addPage(mWelcomePage);
        }

        // It's possible that the user has already run the command line tools
        // such as ddms and has agreed to usage statistics collection, but has never
        // run ADT which is why the wizard was opened. No need to ask again.
        if (mShowUsagePage && !mStore.hasPingId()) {
            mUsagePage = new UsagePermissionPage();
            addPage(mUsagePage);
        }
    }

    @Override
    public boolean performFinish() {
        if (mUsagePage != null) {
            boolean isUsageCollectionApproved = mUsagePage.isUsageCollectionApproved();
            DdmsPreferenceStore store = new DdmsPreferenceStore();

            // Workaround: Store a new ping id if one doesn't exist, regardless of
            // whether usage statistics gathering is enabled, to ensure that ddms and
            // ADT agree upon whether usage data collection is enabled. The reason this
            // is necessary is that the Eclipse PreferenceStore optimizes out writing
            // property values that equal their default values, and in our case, the
            // default value for usage-collection is "false", so it just doesn't write
            // it into the config file is the user opts out - which means that nothing
            // is written in ddms.config. That works in the sense that the getter returns
            // "usage collection"=false, but it doesn't work in the sense that it looks
            // like the property has not yet been decided by the user. DDMS will look at
            // the existence of a ping id to see whether we've already considered the
            // question, so do the same here.
            if (!store.hasPingId()) {
                store.generateNewPingId();
            }

            store.setPingOptIn(isUsageCollectionApproved);
        }

        if (mWelcomePage != null) {
            // Read out wizard settings immediately; we will perform the actual work
            // after the wizard window has been taken down and it's too late to read the
            // settings then
            final File path = mWelcomePage.getPath();
            final boolean installCommon = mWelcomePage.isInstallCommon();
            final boolean installLatest = mWelcomePage.isInstallLatest();
            final boolean createNew = mWelcomePage.isCreateNew();

            // Perform installation asynchronously since it takes a while.
            getShell().getDisplay().asyncExec(new Runnable() {
                @Override
                public void run() {
                    if (createNew) {
                        try {
                            Set<Integer> apiLevels = new HashSet<Integer>();
                            if (installCommon) {
                                apiLevels.add(8);
                            }
                            if (installLatest) {
                                apiLevels.add(AdtUpdateDialog.USE_MAX_REMOTE_API_LEVEL);
                            }
                            installSdk(path, apiLevels);
                        } catch (Exception e) {
                            AdtPlugin.logAndPrintError(e, "ADT Welcome Wizard",
                                    "Installation failed");
                        }
                    }

                    // Set SDK path after installation since this will trigger a SDK refresh.
                    AdtPrefs.getPrefs().setSdkLocation(path);
                }
            });
        }

        // The wizard always succeeds, even if installation fails or is aborted
        return true;
    }

    /**
     * Trigger the install window. It will connect to the repository, display
     * a confirmation window showing which packages are selected for install
     * and display a progress dialog during installation.
     */
    private boolean installSdk(File path, Set<Integer> apiLevels) {
        if (!path.isDirectory()) {
            if (!path.mkdirs()) {
                AdtPlugin.logAndPrintError(null, "ADT Welcome Wizard",
                        "Failed to create directory %1$s",
                        path.getAbsolutePath());
                return false;
            }
        }

        // Get a shell to use for the SDK installation. There are cases where getActiveShell
        // returns null so attempt to obtain it through other means.
        Display display = AdtPlugin.getDisplay();
        Shell shell = display.getActiveShell();
        if (shell == null) {
            IWorkbench workbench = PlatformUI.getWorkbench();
            IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
            if (window != null) {
                shell = window.getShell();
            }
        }
        boolean disposeShell = false;
        if (shell == null) {
            shell = new Shell(display);
            AdtPlugin.log(IStatus.WARNING, "No parent shell for SDK installation dialog");
            disposeShell = true;
        }

        AdtUpdateDialog updater = new AdtUpdateDialog(
                shell,
                new AdtConsoleSdkLog(),
                path.getAbsolutePath());
        // Note: we don't have to specify tools & platform-tools since they
        // are required dependencies of any platform.
        boolean result = updater.installNewSdk(apiLevels);

        // TODO: Install extra package here as well since it is now core to most of
        // the templates
        // if (result) {
        //     updater.installExtraPackage(vendor, path);
        // }

        if (disposeShell) {
            shell.dispose();
        }

        if (!result) {
            AdtPlugin.printErrorToConsole("Failed to install Android SDK.");
            return false;
        }

        return true;
    }
}