• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.sdkuilib.internal.tasks;
18 
19 import com.android.sdklib.internal.repository.ITaskMonitor;
20 import com.android.sdklib.internal.repository.UserCredentials;
21 
22 /**
23  * Internal class that implements the logic of an {@link ITaskMonitor}.
24  * It doesn't deal with any UI directly. Instead it delegates the UI to
25  * the provided {@link IProgressUiProvider}.
26  */
27 class TaskMonitorImpl implements ITaskMonitor {
28 
29     private static final double MAX_COUNT = 10000.0;
30 
31     private interface ISubTaskMonitor extends ITaskMonitor {
subIncProgress(double realDelta)32         public void subIncProgress(double realDelta);
33     }
34 
35     private double mIncCoef = 0;
36     private double mValue = 0;
37     private final IProgressUiProvider mUi;
38 
39     /**
40      * Returns true if the given {@code monitor} is an instance of {@link TaskMonitorImpl}
41      * or its private SubTaskMonitor.
42      */
isTaskMonitorImpl(ITaskMonitor monitor)43     public static boolean isTaskMonitorImpl(ITaskMonitor monitor) {
44         return monitor instanceof TaskMonitorImpl || monitor instanceof SubTaskMonitor;
45     }
46 
47     /**
48      * Constructs a new {@link TaskMonitorImpl} that relies on the given
49      * {@link IProgressUiProvider} to change the user interface.
50      * @param ui The {@link IProgressUiProvider}. Cannot be null.
51      */
TaskMonitorImpl(IProgressUiProvider ui)52     public TaskMonitorImpl(IProgressUiProvider ui) {
53         mUi = ui;
54     }
55 
56     /** Returns the {@link IProgressUiProvider} passed to the constructor. */
getUiProvider()57     public IProgressUiProvider getUiProvider() {
58         return mUi;
59     }
60 
61     /**
62      * Sets the description in the current task dialog.
63      * This method can be invoked from a non-UI thread.
64      */
65     @Override
setDescription(String format, Object... args)66     public void setDescription(String format, Object... args) {
67         final String text = String.format(format, args);
68         mUi.setDescription(text);
69     }
70 
71     /**
72      * Logs a "normal" information line.
73      * This method can be invoked from a non-UI thread.
74      */
75     @Override
log(String format, Object... args)76     public void log(String format, Object... args) {
77         String text = String.format(format, args);
78         mUi.log(text);
79     }
80 
81     /**
82      * Logs an "error" information line.
83      * This method can be invoked from a non-UI thread.
84      */
85     @Override
logError(String format, Object... args)86     public void logError(String format, Object... args) {
87         String text = String.format(format, args);
88         mUi.logError(text);
89     }
90 
91     /**
92      * Logs a "verbose" information line, that is extra details which are typically
93      * not that useful for the end-user and might be hidden until explicitly shown.
94      * This method can be invoked from a non-UI thread.
95      */
96     @Override
logVerbose(String format, Object... args)97     public void logVerbose(String format, Object... args) {
98         String text = String.format(format, args);
99         mUi.logVerbose(text);
100     }
101 
102     /**
103      * Sets the max value of the progress bar.
104      * This method can be invoked from a non-UI thread.
105      *
106      * Weird things will happen if setProgressMax is called multiple times
107      * *after* {@link #incProgress(int)}: we don't try to adjust it on the
108      * fly.
109      */
110     @Override
setProgressMax(int max)111     public void setProgressMax(int max) {
112         assert max > 0;
113         // Always set the dialog's progress max to 10k since it only handles
114         // integers and we want to have a better inner granularity. Instead
115         // we use the max to compute a coefficient for inc deltas.
116         mUi.setProgressMax((int) MAX_COUNT);
117         mIncCoef = max > 0 ? MAX_COUNT / max : 0;
118         assert mIncCoef > 0;
119     }
120 
121     @Override
getProgressMax()122     public int getProgressMax() {
123         return mIncCoef > 0 ? (int) (MAX_COUNT / mIncCoef) : 0;
124     }
125 
126     /**
127      * Increments the current value of the progress bar.
128      *
129      * This method can be invoked from a non-UI thread.
130      */
131     @Override
incProgress(int delta)132     public void incProgress(int delta) {
133         if (delta > 0 && mIncCoef > 0) {
134             internalIncProgress(delta * mIncCoef);
135         }
136     }
137 
internalIncProgress(double realDelta)138     private void internalIncProgress(double realDelta) {
139         mValue += realDelta;
140         mUi.setProgress((int)mValue);
141     }
142 
143     /**
144      * Returns the current value of the progress bar,
145      * between 0 and up to {@link #setProgressMax(int)} - 1.
146      *
147      * This method can be invoked from a non-UI thread.
148      */
149     @Override
getProgress()150     public int getProgress() {
151         // mIncCoef is 0 if setProgressMax hasn't been used yet.
152         return mIncCoef > 0 ? (int)(mUi.getProgress() / mIncCoef) : 0;
153     }
154 
155     /**
156      * Returns true if the "Cancel" button was selected.
157      * It is up to the task thread to pool this and exit.
158      */
159     @Override
isCancelRequested()160     public boolean isCancelRequested() {
161         return mUi.isCancelRequested();
162     }
163 
164     /**
165      * Displays a yes/no question dialog box.
166      *
167      * This implementation allow this to be called from any thread, it
168      * makes sure the dialog is opened synchronously in the ui thread.
169      *
170      * @param title The title of the dialog box
171      * @param message The error message
172      * @return true if YES was clicked.
173      */
174     @Override
displayPrompt(final String title, final String message)175     public boolean displayPrompt(final String title, final String message) {
176         return mUi.displayPrompt(title, message);
177     }
178 
179     /**
180      * Displays a Login/Password dialog. This implementation allows this method to be
181      * called from any thread, it makes sure the dialog is opened synchronously
182      * in the ui thread.
183      *
184      * @param title The title of the dialog box
185      * @param message Message to be displayed
186      * @return Pair with entered login/password. Login is always the first
187      *         element and Password is always the second. If any error occurs a
188      *         pair with empty strings is returned.
189      */
190     @Override
displayLoginCredentialsPrompt(String title, String message)191     public UserCredentials displayLoginCredentialsPrompt(String title, String message) {
192         return mUi.displayLoginCredentialsPrompt(title, message);
193     }
194 
195     /**
196      * Creates a sub-monitor that will use up to tickCount on the progress bar.
197      * tickCount must be 1 or more.
198      */
199     @Override
createSubMonitor(int tickCount)200     public ITaskMonitor createSubMonitor(int tickCount) {
201         assert mIncCoef > 0;
202         assert tickCount > 0;
203         return new SubTaskMonitor(this, null, mValue, tickCount * mIncCoef);
204     }
205 
206     // ----- ISdkLog interface ----
207 
208     @Override
error(Throwable throwable, String errorFormat, Object... arg)209     public void error(Throwable throwable, String errorFormat, Object... arg) {
210         if (errorFormat != null) {
211             logError("Error: " + errorFormat, arg);
212         }
213 
214         if (throwable != null) {
215             logError("%s", throwable.getMessage()); //$NON-NLS-1$
216         }
217     }
218 
219     @Override
warning(String warningFormat, Object... arg)220     public void warning(String warningFormat, Object... arg) {
221         log("Warning: " + warningFormat, arg);
222     }
223 
224     @Override
printf(String msgFormat, Object... arg)225     public void printf(String msgFormat, Object... arg) {
226         log(msgFormat, arg);
227     }
228 
229     // ----- Sub Monitor -----
230 
231     private static class SubTaskMonitor implements ISubTaskMonitor {
232 
233         private final TaskMonitorImpl mRoot;
234         private final ISubTaskMonitor mParent;
235         private final double mStart;
236         private final double mSpan;
237         private double mSubValue;
238         private double mSubCoef;
239 
240         /**
241          * Creates a new sub task monitor which will work for the given range [start, start+span]
242          * in its parent.
243          *
244          * @param taskMonitor The ProgressTask root
245          * @param parent The immediate parent. Can be the null or another sub task monitor.
246          * @param start The start value in the root's coordinates
247          * @param span The span value in the root's coordinates
248          */
SubTaskMonitor(TaskMonitorImpl taskMonitor, ISubTaskMonitor parent, double start, double span)249         public SubTaskMonitor(TaskMonitorImpl taskMonitor,
250                 ISubTaskMonitor parent,
251                 double start,
252                 double span) {
253             mRoot = taskMonitor;
254             mParent = parent;
255             mStart = start;
256             mSpan = span;
257             mSubValue = start;
258         }
259 
260         @Override
isCancelRequested()261         public boolean isCancelRequested() {
262             return mRoot.isCancelRequested();
263         }
264 
265         @Override
setDescription(String format, Object... args)266         public void setDescription(String format, Object... args) {
267             mRoot.setDescription(format, args);
268         }
269 
270         @Override
log(String format, Object... args)271         public void log(String format, Object... args) {
272             mRoot.log(format, args);
273         }
274 
275         @Override
logError(String format, Object... args)276         public void logError(String format, Object... args) {
277             mRoot.logError(format, args);
278         }
279 
280         @Override
logVerbose(String format, Object... args)281         public void logVerbose(String format, Object... args) {
282             mRoot.logVerbose(format, args);
283         }
284 
285         @Override
setProgressMax(int max)286         public void setProgressMax(int max) {
287             assert max > 0;
288             mSubCoef = max > 0 ? mSpan / max : 0;
289             assert mSubCoef > 0;
290         }
291 
292         @Override
getProgressMax()293         public int getProgressMax() {
294             return mSubCoef > 0 ? (int) (mSpan / mSubCoef) : 0;
295         }
296 
297         @Override
getProgress()298         public int getProgress() {
299             // subCoef can be 0 if setProgressMax() and incProgress() haven't been called yet
300             assert mSubValue == mStart || mSubCoef > 0;
301             return mSubCoef > 0 ? (int)((mSubValue - mStart) / mSubCoef) : 0;
302         }
303 
304         @Override
incProgress(int delta)305         public void incProgress(int delta) {
306             if (delta > 0 && mSubCoef > 0) {
307                 subIncProgress(delta * mSubCoef);
308             }
309         }
310 
311         @Override
subIncProgress(double realDelta)312         public void subIncProgress(double realDelta) {
313             mSubValue += realDelta;
314             if (mParent != null) {
315                 mParent.subIncProgress(realDelta);
316             } else {
317                 mRoot.internalIncProgress(realDelta);
318             }
319         }
320 
321         @Override
displayPrompt(String title, String message)322         public boolean displayPrompt(String title, String message) {
323             return mRoot.displayPrompt(title, message);
324         }
325 
326         @Override
displayLoginCredentialsPrompt(String title, String message)327         public UserCredentials displayLoginCredentialsPrompt(String title, String message) {
328             return mRoot.displayLoginCredentialsPrompt(title, message);
329         }
330 
331         @Override
createSubMonitor(int tickCount)332         public ITaskMonitor createSubMonitor(int tickCount) {
333             assert mSubCoef > 0;
334             assert tickCount > 0;
335             return new SubTaskMonitor(mRoot,
336                     this,
337                     mSubValue,
338                     tickCount * mSubCoef);
339         }
340 
341         // ----- ISdkLog interface ----
342 
343         @Override
error(Throwable throwable, String errorFormat, Object... arg)344         public void error(Throwable throwable, String errorFormat, Object... arg) {
345             mRoot.error(throwable, errorFormat, arg);
346         }
347 
348         @Override
warning(String warningFormat, Object... arg)349         public void warning(String warningFormat, Object... arg) {
350             mRoot.warning(warningFormat, arg);
351         }
352 
353         @Override
printf(String msgFormat, Object... arg)354         public void printf(String msgFormat, Object... arg) {
355             mRoot.printf(msgFormat, arg);
356         }
357     }
358 }
359