blob: 3d088d18aaed93716096a6ca658761cf3c57d57a [file] [log] [blame]
Owen Linf9a0a432011-08-17 22:07:43 +08001/*
2 * Copyright (C) 2010 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
17package com.android.gallery3d.ui;
18
Ray Chen0c1f2c82011-10-05 14:32:58 +080019import android.app.Activity;
Ray Chen67098d12012-04-05 17:25:43 +080020import android.app.AlertDialog;
Ray Chen0c1f2c82011-10-05 14:32:58 +080021import android.app.ProgressDialog;
22import android.content.Context;
Ray Chen67098d12012-04-05 17:25:43 +080023import android.content.DialogInterface;
Owen Lind759b7c2012-05-16 15:32:02 -070024import android.content.DialogInterface.OnCancelListener;
Ray Chen67098d12012-04-05 17:25:43 +080025import android.content.DialogInterface.OnClickListener;
Ray Chen0c1f2c82011-10-05 14:32:58 +080026import android.content.Intent;
27import android.os.Handler;
28import android.os.Message;
Ray Chen0c1f2c82011-10-05 14:32:58 +080029
John Reck37215292012-10-30 17:34:20 -070030import com.actionbarsherlock.view.Menu;
31import com.actionbarsherlock.view.MenuItem;
Owen Linf9a0a432011-08-17 22:07:43 +080032import com.android.gallery3d.R;
Owen Linb21b8e52012-08-24 12:25:57 +080033import com.android.gallery3d.app.AbstractGalleryActivity;
Owen Linf9a0a432011-08-17 22:07:43 +080034import com.android.gallery3d.app.CropImage;
John Reck37215292012-10-30 17:34:20 -070035import com.android.gallery3d.common.ApiHelper;
Owen Linf9a0a432011-08-17 22:07:43 +080036import com.android.gallery3d.common.Utils;
37import com.android.gallery3d.data.DataManager;
38import com.android.gallery3d.data.MediaItem;
39import com.android.gallery3d.data.MediaObject;
40import com.android.gallery3d.data.Path;
Ruben Brunk5aa454b2012-10-25 15:53:42 -070041import com.android.gallery3d.filtershow.FilterShowActivity;
Owen Linf9a0a432011-08-17 22:07:43 +080042import com.android.gallery3d.util.Future;
43import com.android.gallery3d.util.GalleryUtils;
44import com.android.gallery3d.util.ThreadPool.Job;
45import com.android.gallery3d.util.ThreadPool.JobContext;
46
Owen Linf9a0a432011-08-17 22:07:43 +080047import java.util.ArrayList;
48
49public class MenuExecutor {
50 @SuppressWarnings("unused")
51 private static final String TAG = "MenuExecutor";
52
53 private static final int MSG_TASK_COMPLETE = 1;
54 private static final int MSG_TASK_UPDATE = 2;
Bobby Georgescuba50b942012-08-08 00:09:50 -070055 private static final int MSG_TASK_START = 3;
56 private static final int MSG_DO_SHARE = 4;
Owen Linf9a0a432011-08-17 22:07:43 +080057
58 public static final int EXECUTION_RESULT_SUCCESS = 1;
59 public static final int EXECUTION_RESULT_FAIL = 2;
60 public static final int EXECUTION_RESULT_CANCEL = 3;
61
62 private ProgressDialog mDialog;
63 private Future<?> mTask;
Chih-Chung Chang6b891c62012-06-07 20:09:13 +080064 // wait the operation to finish when we want to stop it.
65 private boolean mWaitOnStop;
Owen Linf9a0a432011-08-17 22:07:43 +080066
Owen Linb21b8e52012-08-24 12:25:57 +080067 private final AbstractGalleryActivity mActivity;
Owen Linf9a0a432011-08-17 22:07:43 +080068 private final SelectionManager mSelectionManager;
69 private final Handler mHandler;
70
Chih-Chung Chang6b891c62012-06-07 20:09:13 +080071 private static ProgressDialog createProgressDialog(
Owen Linf9a0a432011-08-17 22:07:43 +080072 Context context, int titleId, int progressMax) {
73 ProgressDialog dialog = new ProgressDialog(context);
74 dialog.setTitle(titleId);
75 dialog.setMax(progressMax);
76 dialog.setCancelable(false);
77 dialog.setIndeterminate(false);
78 if (progressMax > 1) {
79 dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
80 }
Owen Linf9a0a432011-08-17 22:07:43 +080081 return dialog;
82 }
83
84 public interface ProgressListener {
Owen Lind759b7c2012-05-16 15:32:02 -070085 public void onConfirmDialogShown();
86 public void onConfirmDialogDismissed(boolean confirmed);
Bobby Georgescuba50b942012-08-08 00:09:50 -070087 public void onProgressStart();
Owen Linf9a0a432011-08-17 22:07:43 +080088 public void onProgressUpdate(int index);
89 public void onProgressComplete(int result);
90 }
91
92 public MenuExecutor(
Owen Linb21b8e52012-08-24 12:25:57 +080093 AbstractGalleryActivity activity, SelectionManager selectionManager) {
Owen Linf9a0a432011-08-17 22:07:43 +080094 mActivity = Utils.checkNotNull(activity);
95 mSelectionManager = Utils.checkNotNull(selectionManager);
96 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
97 @Override
98 public void handleMessage(Message message) {
99 switch (message.what) {
Bobby Georgescuba50b942012-08-08 00:09:50 -0700100 case MSG_TASK_START: {
101 if (message.obj != null) {
102 ProgressListener listener = (ProgressListener) message.obj;
103 listener.onProgressStart();
104 }
105 break;
106 }
Owen Linf9a0a432011-08-17 22:07:43 +0800107 case MSG_TASK_COMPLETE: {
Ray Chenb2b45182011-08-31 16:37:04 +0800108 stopTaskAndDismissDialog();
Owen Linf9a0a432011-08-17 22:07:43 +0800109 if (message.obj != null) {
110 ProgressListener listener = (ProgressListener) message.obj;
111 listener.onProgressComplete(message.arg1);
112 }
113 mSelectionManager.leaveSelectionMode();
114 break;
115 }
116 case MSG_TASK_UPDATE: {
117 if (mDialog != null) mDialog.setProgress(message.arg1);
118 if (message.obj != null) {
119 ProgressListener listener = (ProgressListener) message.obj;
120 listener.onProgressUpdate(message.arg1);
121 }
122 break;
123 }
124 case MSG_DO_SHARE: {
125 ((Activity) mActivity).startActivity((Intent) message.obj);
126 break;
127 }
128 }
129 }
130 };
131 }
132
Ray Chenb2b45182011-08-31 16:37:04 +0800133 private void stopTaskAndDismissDialog() {
Owen Linf9a0a432011-08-17 22:07:43 +0800134 if (mTask != null) {
Chih-Chung Chang6b891c62012-06-07 20:09:13 +0800135 if (!mWaitOnStop) mTask.cancel();
Owen Linf9a0a432011-08-17 22:07:43 +0800136 mTask.waitDone();
137 mDialog.dismiss();
138 mDialog = null;
139 mTask = null;
140 }
141 }
142
Ray Chenb2b45182011-08-31 16:37:04 +0800143 public void pause() {
144 stopTaskAndDismissDialog();
145 }
146
Owen Linf9a0a432011-08-17 22:07:43 +0800147 private void onProgressUpdate(int index, ProgressListener listener) {
148 mHandler.sendMessage(
149 mHandler.obtainMessage(MSG_TASK_UPDATE, index, 0, listener));
150 }
151
Bobby Georgescuba50b942012-08-08 00:09:50 -0700152 private void onProgressStart(ProgressListener listener) {
153 mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_START, listener));
154 }
155
Owen Linf9a0a432011-08-17 22:07:43 +0800156 private void onProgressComplete(int result, ProgressListener listener) {
157 mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_COMPLETE, result, 0, listener));
158 }
159
Owen Linb21b8e52012-08-24 12:25:57 +0800160 public static void updateMenuOperation(Menu menu, int supported) {
Owen Linf9a0a432011-08-17 22:07:43 +0800161 boolean supportDelete = (supported & MediaObject.SUPPORT_DELETE) != 0;
162 boolean supportRotate = (supported & MediaObject.SUPPORT_ROTATE) != 0;
163 boolean supportCrop = (supported & MediaObject.SUPPORT_CROP) != 0;
Teng-Hui Zhu5e926682012-09-26 14:20:46 -0700164 boolean supportTrim = (supported & MediaObject.SUPPORT_TRIM) != 0;
Teng-Hui Zhu648b3392012-11-13 10:39:26 -0800165 boolean supportMute = (supported & MediaObject.SUPPORT_MUTE) != 0;
Owen Linf9a0a432011-08-17 22:07:43 +0800166 boolean supportShare = (supported & MediaObject.SUPPORT_SHARE) != 0;
167 boolean supportSetAs = (supported & MediaObject.SUPPORT_SETAS) != 0;
168 boolean supportShowOnMap = (supported & MediaObject.SUPPORT_SHOW_ON_MAP) != 0;
169 boolean supportCache = (supported & MediaObject.SUPPORT_CACHE) != 0;
170 boolean supportEdit = (supported & MediaObject.SUPPORT_EDIT) != 0;
171 boolean supportInfo = (supported & MediaObject.SUPPORT_INFO) != 0;
172 boolean supportImport = (supported & MediaObject.SUPPORT_IMPORT) != 0;
173
Owen Linb21b8e52012-08-24 12:25:57 +0800174 setMenuItemVisible(menu, R.id.action_delete, supportDelete);
175 setMenuItemVisible(menu, R.id.action_rotate_ccw, supportRotate);
176 setMenuItemVisible(menu, R.id.action_rotate_cw, supportRotate);
177 setMenuItemVisible(menu, R.id.action_crop, supportCrop);
Teng-Hui Zhu50ea2d22012-08-23 16:45:11 -0700178 setMenuItemVisible(menu, R.id.action_trim, supportTrim);
Teng-Hui Zhu648b3392012-11-13 10:39:26 -0800179 setMenuItemVisible(menu, R.id.action_mute, supportMute);
George Mount4b4dbd22012-10-18 14:20:39 -0700180 // Hide panorama until call to updateMenuForPanorama corrects it
181 setMenuItemVisible(menu, R.id.action_share_panorama, false);
Owen Linb21b8e52012-08-24 12:25:57 +0800182 setMenuItemVisible(menu, R.id.action_share, supportShare);
183 setMenuItemVisible(menu, R.id.action_setas, supportSetAs);
184 setMenuItemVisible(menu, R.id.action_show_on_map, supportShowOnMap);
185 setMenuItemVisible(menu, R.id.action_edit, supportEdit);
186 setMenuItemVisible(menu, R.id.action_details, supportInfo);
187 setMenuItemVisible(menu, R.id.action_import, supportImport);
188 }
189
George Mount4b4dbd22012-10-18 14:20:39 -0700190 public static void updateMenuForPanorama(Menu menu, boolean shareAsPanorama360,
191 boolean disablePanorama360Options) {
192 setMenuItemVisible(menu, R.id.action_share_panorama, shareAsPanorama360);
193 if (disablePanorama360Options) {
194 setMenuItemVisible(menu, R.id.action_rotate_ccw, false);
195 setMenuItemVisible(menu, R.id.action_rotate_cw, false);
George Mount4b4dbd22012-10-18 14:20:39 -0700196 }
197 }
198
Owen Linb21b8e52012-08-24 12:25:57 +0800199 private static void setMenuItemVisible(Menu menu, int itemId, boolean visible) {
200 MenuItem item = menu.findItem(itemId);
201 if (item != null) item.setVisible(visible);
Owen Linf9a0a432011-08-17 22:07:43 +0800202 }
203
204 private Path getSingleSelectedPath() {
205 ArrayList<Path> ids = mSelectionManager.getSelected(true);
206 Utils.assertTrue(ids.size() == 1);
207 return ids.get(0);
208 }
209
Yuli Huangf50ce2b2012-05-02 00:50:56 +0800210 private Intent getIntentBySingleSelectedPath(String action) {
211 DataManager manager = mActivity.getDataManager();
212 Path path = getSingleSelectedPath();
Mangesh Ghiware5172dee2012-09-27 21:05:41 -0700213 String mimeType = getMimeType(manager.getMediaType(path));
Yuli Huangf50ce2b2012-05-02 00:50:56 +0800214 return new Intent(action).setDataAndType(manager.getContentUri(path), mimeType);
215 }
216
Ray Chen67098d12012-04-05 17:25:43 +0800217 private void onMenuClicked(int action, ProgressListener listener) {
Chih-Chung Chang6b891c62012-06-07 20:09:13 +0800218 onMenuClicked(action, listener, false, true);
219 }
220
221 public void onMenuClicked(int action, ProgressListener listener,
222 boolean waitOnStop, boolean showDialog) {
Owen Linf9a0a432011-08-17 22:07:43 +0800223 int title;
Owen Linf9a0a432011-08-17 22:07:43 +0800224 switch (action) {
225 case R.id.action_select_all:
226 if (mSelectionManager.inSelectAllMode()) {
227 mSelectionManager.deSelectAll();
228 } else {
229 mSelectionManager.selectAll();
230 }
Wu-cheng Li57263d32012-04-30 23:49:17 +0800231 return;
Owen Linf9a0a432011-08-17 22:07:43 +0800232 case R.id.action_crop: {
Ruben Brunk5aa454b2012-10-25 15:53:42 -0700233 Intent intent = getIntentBySingleSelectedPath(FilterShowActivity.CROP_ACTION)
234 .setClass((Activity) mActivity, FilterShowActivity.class);
Owen Linf9a0a432011-08-17 22:07:43 +0800235 ((Activity) mActivity).startActivity(intent);
Wu-cheng Li57263d32012-04-30 23:49:17 +0800236 return;
Owen Linf9a0a432011-08-17 22:07:43 +0800237 }
Yuli Huangf50ce2b2012-05-02 00:50:56 +0800238 case R.id.action_edit: {
239 Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_EDIT)
240 .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
241 ((Activity) mActivity).startActivity(Intent.createChooser(intent, null));
242 return;
243 }
Owen Linf9a0a432011-08-17 22:07:43 +0800244 case R.id.action_setas: {
Yuli Huangf50ce2b2012-05-02 00:50:56 +0800245 Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA)
246 .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
247 intent.putExtra("mimeType", intent.getType());
Owen Lin28cb4162012-08-29 11:53:10 +0800248 Activity activity = mActivity;
Owen Linf9a0a432011-08-17 22:07:43 +0800249 activity.startActivity(Intent.createChooser(
250 intent, activity.getString(R.string.set_as)));
Wu-cheng Li57263d32012-04-30 23:49:17 +0800251 return;
Owen Linf9a0a432011-08-17 22:07:43 +0800252 }
Ray Chen67098d12012-04-05 17:25:43 +0800253 case R.id.action_delete:
Owen Linf9a0a432011-08-17 22:07:43 +0800254 title = R.string.delete;
255 break;
256 case R.id.action_rotate_cw:
257 title = R.string.rotate_right;
258 break;
259 case R.id.action_rotate_ccw:
260 title = R.string.rotate_left;
261 break;
262 case R.id.action_show_on_map:
263 title = R.string.show_on_map;
264 break;
Owen Linf9a0a432011-08-17 22:07:43 +0800265 case R.id.action_import:
266 title = R.string.Import;
267 break;
268 default:
Ray Chen67098d12012-04-05 17:25:43 +0800269 return;
Owen Linf9a0a432011-08-17 22:07:43 +0800270 }
Chih-Chung Chang6b891c62012-06-07 20:09:13 +0800271 startAction(action, title, listener, waitOnStop, showDialog);
Ray Chen67098d12012-04-05 17:25:43 +0800272 }
273
Owen Lind759b7c2012-05-16 15:32:02 -0700274 private class ConfirmDialogListener implements OnClickListener, OnCancelListener {
275 private final int mActionId;
276 private final ProgressListener mListener;
277
278 public ConfirmDialogListener(int actionId, ProgressListener listener) {
279 mActionId = actionId;
280 mListener = listener;
281 }
282
283 @Override
284 public void onClick(DialogInterface dialog, int which) {
285 if (which == DialogInterface.BUTTON_POSITIVE) {
286 if (mListener != null) {
287 mListener.onConfirmDialogDismissed(true);
288 }
289 onMenuClicked(mActionId, mListener);
290 } else {
291 if (mListener != null) {
292 mListener.onConfirmDialogDismissed(false);
293 }
294 }
295 }
296
297 @Override
298 public void onCancel(DialogInterface dialog) {
299 if (mListener != null) {
300 mListener.onConfirmDialogDismissed(false);
301 }
302 }
303 }
304
Ray Chen9a033b02012-05-15 11:22:21 +0800305 public void onMenuClicked(MenuItem menuItem, String confirmMsg,
Ray Chen67098d12012-04-05 17:25:43 +0800306 final ProgressListener listener) {
307 final int action = menuItem.getItemId();
308
Ray Chen9a033b02012-05-15 11:22:21 +0800309 if (confirmMsg != null) {
Owen Lind759b7c2012-05-16 15:32:02 -0700310 if (listener != null) listener.onConfirmDialogShown();
311 ConfirmDialogListener cdl = new ConfirmDialogListener(action, listener);
Ray Chen67098d12012-04-05 17:25:43 +0800312 new AlertDialog.Builder(mActivity.getAndroidContext())
Ray Chen9a033b02012-05-15 11:22:21 +0800313 .setMessage(confirmMsg)
Owen Lind759b7c2012-05-16 15:32:02 -0700314 .setOnCancelListener(cdl)
315 .setPositiveButton(R.string.ok, cdl)
316 .setNegativeButton(R.string.cancel, cdl)
317 .create().show();
Ray Chen67098d12012-04-05 17:25:43 +0800318 } else {
319 onMenuClicked(action, listener);
320 }
Owen Linf9a0a432011-08-17 22:07:43 +0800321 }
322
323 public void startAction(int action, int title, ProgressListener listener) {
Chih-Chung Chang6b891c62012-06-07 20:09:13 +0800324 startAction(action, title, listener, false, true);
325 }
326
327 public void startAction(int action, int title, ProgressListener listener,
328 boolean waitOnStop, boolean showDialog) {
Owen Linf9a0a432011-08-17 22:07:43 +0800329 ArrayList<Path> ids = mSelectionManager.getSelected(false);
Ray Chenb2b45182011-08-31 16:37:04 +0800330 stopTaskAndDismissDialog();
Owen Linf9a0a432011-08-17 22:07:43 +0800331
Owen Lin28cb4162012-08-29 11:53:10 +0800332 Activity activity = mActivity;
Chih-Chung Chang6b891c62012-06-07 20:09:13 +0800333 mDialog = createProgressDialog(activity, title, ids.size());
334 if (showDialog) {
335 mDialog.show();
336 }
Owen Linf9a0a432011-08-17 22:07:43 +0800337 MediaOperation operation = new MediaOperation(action, ids, listener);
338 mTask = mActivity.getThreadPool().submit(operation, null);
Chih-Chung Chang6b891c62012-06-07 20:09:13 +0800339 mWaitOnStop = waitOnStop;
Owen Linf9a0a432011-08-17 22:07:43 +0800340 }
341
Mangesh Ghiware5172dee2012-09-27 21:05:41 -0700342 public static String getMimeType(int type) {
Owen Linf9a0a432011-08-17 22:07:43 +0800343 switch (type) {
344 case MediaObject.MEDIA_TYPE_IMAGE :
Mangesh Ghiware5172dee2012-09-27 21:05:41 -0700345 return GalleryUtils.MIME_TYPE_IMAGE;
Owen Linf9a0a432011-08-17 22:07:43 +0800346 case MediaObject.MEDIA_TYPE_VIDEO :
Mangesh Ghiware5172dee2012-09-27 21:05:41 -0700347 return GalleryUtils.MIME_TYPE_VIDEO;
348 default: return GalleryUtils.MIME_TYPE_ALL;
Owen Linf9a0a432011-08-17 22:07:43 +0800349 }
350 }
351
352 private boolean execute(
353 DataManager manager, JobContext jc, int cmd, Path path) {
354 boolean result = true;
Ray Chenb2b45182011-08-31 16:37:04 +0800355 Log.v(TAG, "Execute cmd: " + cmd + " for " + path);
356 long startTime = System.currentTimeMillis();
357
Owen Linf9a0a432011-08-17 22:07:43 +0800358 switch (cmd) {
Ray Chen67098d12012-04-05 17:25:43 +0800359 case R.id.action_delete:
Owen Linf9a0a432011-08-17 22:07:43 +0800360 manager.delete(path);
361 break;
362 case R.id.action_rotate_cw:
363 manager.rotate(path, 90);
364 break;
365 case R.id.action_rotate_ccw:
366 manager.rotate(path, -90);
367 break;
368 case R.id.action_toggle_full_caching: {
369 MediaObject obj = manager.getMediaObject(path);
370 int cacheFlag = obj.getCacheFlag();
371 if (cacheFlag == MediaObject.CACHE_FLAG_FULL) {
372 cacheFlag = MediaObject.CACHE_FLAG_SCREENNAIL;
373 } else {
374 cacheFlag = MediaObject.CACHE_FLAG_FULL;
375 }
376 obj.cache(cacheFlag);
377 break;
378 }
379 case R.id.action_show_on_map: {
380 MediaItem item = (MediaItem) manager.getMediaObject(path);
381 double latlng[] = new double[2];
382 item.getLatLong(latlng);
383 if (GalleryUtils.isValidLocation(latlng[0], latlng[1])) {
Owen Lin28cb4162012-08-29 11:53:10 +0800384 GalleryUtils.showOnMap(mActivity, latlng[0], latlng[1]);
Owen Linf9a0a432011-08-17 22:07:43 +0800385 }
386 break;
387 }
388 case R.id.action_import: {
389 MediaObject obj = manager.getMediaObject(path);
390 result = obj.Import();
391 break;
392 }
Owen Linf9a0a432011-08-17 22:07:43 +0800393 default:
394 throw new AssertionError();
395 }
Ray Chenb2b45182011-08-31 16:37:04 +0800396 Log.v(TAG, "It takes " + (System.currentTimeMillis() - startTime) +
397 " ms to execute cmd for " + path);
Owen Linf9a0a432011-08-17 22:07:43 +0800398 return result;
399 }
400
401 private class MediaOperation implements Job<Void> {
402 private final ArrayList<Path> mItems;
403 private final int mOperation;
404 private final ProgressListener mListener;
405
Chih-Chung Chang6b891c62012-06-07 20:09:13 +0800406 public MediaOperation(int operation, ArrayList<Path> items,
407 ProgressListener listener) {
Owen Linf9a0a432011-08-17 22:07:43 +0800408 mOperation = operation;
409 mItems = items;
410 mListener = listener;
411 }
412
Ahbong Chang78179792012-07-30 11:34:13 +0800413 @Override
Owen Linf9a0a432011-08-17 22:07:43 +0800414 public Void run(JobContext jc) {
415 int index = 0;
416 DataManager manager = mActivity.getDataManager();
417 int result = EXECUTION_RESULT_SUCCESS;
Ray Chenb2b45182011-08-31 16:37:04 +0800418 try {
Bobby Georgescuba50b942012-08-08 00:09:50 -0700419 onProgressStart(mListener);
Ray Chenb2b45182011-08-31 16:37:04 +0800420 for (Path id : mItems) {
421 if (jc.isCancelled()) {
422 result = EXECUTION_RESULT_CANCEL;
423 break;
424 }
425 if (!execute(manager, jc, mOperation, id)) {
426 result = EXECUTION_RESULT_FAIL;
427 }
428 onProgressUpdate(index++, mListener);
Owen Linf9a0a432011-08-17 22:07:43 +0800429 }
Ray Chenb2b45182011-08-31 16:37:04 +0800430 } catch (Throwable th) {
431 Log.e(TAG, "failed to execute operation " + mOperation
432 + " : " + th);
433 } finally {
434 onProgressComplete(result, mListener);
Owen Linf9a0a432011-08-17 22:07:43 +0800435 }
Owen Linf9a0a432011-08-17 22:07:43 +0800436 return null;
437 }
438 }
439}