summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/ingest
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/ingest')
-rw-r--r--src/com/android/gallery3d/ingest/ImportTask.java95
-rw-r--r--src/com/android/gallery3d/ingest/IngestActivity.java570
-rw-r--r--src/com/android/gallery3d/ingest/IngestService.java320
-rw-r--r--src/com/android/gallery3d/ingest/MtpDeviceIndex.java596
-rw-r--r--src/com/android/gallery3d/ingest/SimpleDate.java114
-rw-r--r--src/com/android/gallery3d/ingest/adapter/CheckBroker.java56
-rw-r--r--src/com/android/gallery3d/ingest/adapter/MtpAdapter.java192
-rw-r--r--src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java102
-rw-r--r--src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java29
-rw-r--r--src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java106
-rw-r--r--src/com/android/gallery3d/ingest/ui/DateTileView.java107
-rw-r--r--src/com/android/gallery3d/ingest/ui/IngestGridView.java58
-rw-r--r--src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java115
-rw-r--r--src/com/android/gallery3d/ingest/ui/MtpImageView.java280
-rw-r--r--src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java106
15 files changed, 0 insertions, 2846 deletions
diff --git a/src/com/android/gallery3d/ingest/ImportTask.java b/src/com/android/gallery3d/ingest/ImportTask.java
deleted file mode 100644
index 7d2d641a5..000000000
--- a/src/com/android/gallery3d/ingest/ImportTask.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest;
-
-import android.content.Context;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.os.Environment;
-import android.os.PowerManager;
-
-import com.android.gallery3d.util.GalleryUtils;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-public class ImportTask implements Runnable {
-
- public interface Listener {
- void onImportProgress(int visitedCount, int totalCount, String pathIfSuccessful);
-
- void onImportFinish(Collection<MtpObjectInfo> objectsNotImported, int visitedCount);
- }
-
- static private final String WAKELOCK_LABEL = "MTP Import Task";
-
- private Listener mListener;
- private String mDestAlbumName;
- private Collection<MtpObjectInfo> mObjectsToImport;
- private MtpDevice mDevice;
- private PowerManager.WakeLock mWakeLock;
-
- public ImportTask(MtpDevice device, Collection<MtpObjectInfo> objectsToImport,
- String destAlbumName, Context context) {
- mDestAlbumName = destAlbumName;
- mObjectsToImport = objectsToImport;
- mDevice = device;
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, WAKELOCK_LABEL);
- }
-
- public void setListener(Listener listener) {
- mListener = listener;
- }
-
- @Override
- public void run() {
- mWakeLock.acquire();
- try {
- List<MtpObjectInfo> objectsNotImported = new LinkedList<MtpObjectInfo>();
- int visited = 0;
- int total = mObjectsToImport.size();
- mListener.onImportProgress(visited, total, null);
- File dest = new File(Environment.getExternalStorageDirectory(), mDestAlbumName);
- dest.mkdirs();
- for (MtpObjectInfo object : mObjectsToImport) {
- visited++;
- String importedPath = null;
- if (GalleryUtils.hasSpaceForSize(object.getCompressedSize())) {
- importedPath = new File(dest, object.getName()).getAbsolutePath();
- if (!mDevice.importFile(object.getObjectHandle(), importedPath)) {
- importedPath = null;
- }
- }
- if (importedPath == null) {
- objectsNotImported.add(object);
- }
- if (mListener != null) {
- mListener.onImportProgress(visited, total, importedPath);
- }
- }
- if (mListener != null) {
- mListener.onImportFinish(objectsNotImported, visited);
- }
- } finally {
- mListener = null;
- mWakeLock.release();
- }
- }
-}
diff --git a/src/com/android/gallery3d/ingest/IngestActivity.java b/src/com/android/gallery3d/ingest/IngestActivity.java
deleted file mode 100644
index 687e9fd44..000000000
--- a/src/com/android/gallery3d/ingest/IngestActivity.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.res.Configuration;
-import android.database.DataSetObserver;
-import android.mtp.MtpObjectInfo;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.support.v4.view.ViewPager;
-import android.util.SparseBooleanArray;
-import android.view.ActionMode;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AbsListView.MultiChoiceModeListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.adapter.CheckBroker;
-import com.android.gallery3d.ingest.adapter.MtpAdapter;
-import com.android.gallery3d.ingest.adapter.MtpPagerAdapter;
-import com.android.gallery3d.ingest.data.MtpBitmapFetch;
-import com.android.gallery3d.ingest.ui.DateTileView;
-import com.android.gallery3d.ingest.ui.IngestGridView;
-import com.android.gallery3d.ingest.ui.IngestGridView.OnClearChoicesListener;
-
-import java.lang.ref.WeakReference;
-import java.util.Collection;
-
-public class IngestActivity extends Activity implements
- MtpDeviceIndex.ProgressListener, ImportTask.Listener {
-
- private IngestService mHelperService;
- private boolean mActive = false;
- private IngestGridView mGridView;
- private MtpAdapter mAdapter;
- private Handler mHandler;
- private ProgressDialog mProgressDialog;
- private ActionMode mActiveActionMode;
-
- private View mWarningView;
- private TextView mWarningText;
- private int mLastCheckedPosition = 0;
-
- private ViewPager mFullscreenPager;
- private MtpPagerAdapter mPagerAdapter;
- private boolean mFullscreenPagerVisible = false;
-
- private MenuItem mMenuSwitcherItem;
- private MenuItem mActionMenuSwitcherItem;
-
- // The MTP framework components don't give us fine-grained file copy
- // progress updates, so for large photos and videos, we will be stuck
- // with a dialog not updating for a long time. To give the user feedback,
- // we switch to the animated indeterminate progress bar after the timeout
- // specified by INDETERMINATE_SWITCH_TIMEOUT_MS. On the next update from
- // the framework, we switch back to the normal progress bar.
- private static final int INDETERMINATE_SWITCH_TIMEOUT_MS = 3000;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- doBindHelperService();
-
- setContentView(R.layout.ingest_activity_item_list);
- mGridView = (IngestGridView) findViewById(R.id.ingest_gridview);
- mAdapter = new MtpAdapter(this);
- mAdapter.registerDataSetObserver(mMasterObserver);
- mGridView.setAdapter(mAdapter);
- mGridView.setMultiChoiceModeListener(mMultiChoiceModeListener);
- mGridView.setOnItemClickListener(mOnItemClickListener);
- mGridView.setOnClearChoicesListener(mPositionMappingCheckBroker);
-
- mFullscreenPager = (ViewPager) findViewById(R.id.ingest_view_pager);
-
- mHandler = new ItemListHandler(this);
-
- MtpBitmapFetch.configureForContext(this);
- }
-
- private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View itemView, int position, long arg3) {
- mLastCheckedPosition = position;
- mGridView.setItemChecked(position, !mGridView.getCheckedItemPositions().get(position));
- }
- };
-
- private MultiChoiceModeListener mMultiChoiceModeListener = new MultiChoiceModeListener() {
- private boolean mIgnoreItemCheckedStateChanges = false;
-
- private void updateSelectedTitle(ActionMode mode) {
- int count = mGridView.getCheckedItemCount();
- mode.setTitle(getResources().getQuantityString(
- R.plurals.number_of_items_selected, count, count));
- }
-
- @Override
- public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
- boolean checked) {
- if (mIgnoreItemCheckedStateChanges) return;
- if (mAdapter.itemAtPositionIsBucket(position)) {
- SparseBooleanArray checkedItems = mGridView.getCheckedItemPositions();
- mIgnoreItemCheckedStateChanges = true;
- mGridView.setItemChecked(position, false);
-
- // Takes advantage of the fact that SectionIndexer imposes the
- // need to clamp to the valid range
- int nextSectionStart = mAdapter.getPositionForSection(
- mAdapter.getSectionForPosition(position) + 1);
- if (nextSectionStart == position)
- nextSectionStart = mAdapter.getCount();
-
- boolean rangeValue = false; // Value we want to set all of the bucket items to
-
- // Determine if all the items in the bucket are currently checked, so that we
- // can uncheck them, otherwise we will check all items in the bucket.
- for (int i = position + 1; i < nextSectionStart; i++) {
- if (checkedItems.get(i) == false) {
- rangeValue = true;
- break;
- }
- }
-
- // Set all items in the bucket to the desired state
- for (int i = position + 1; i < nextSectionStart; i++) {
- if (checkedItems.get(i) != rangeValue)
- mGridView.setItemChecked(i, rangeValue);
- }
-
- mPositionMappingCheckBroker.onBulkCheckedChange();
- mIgnoreItemCheckedStateChanges = false;
- } else {
- mPositionMappingCheckBroker.onCheckedChange(position, checked);
- }
- mLastCheckedPosition = position;
- updateSelectedTitle(mode);
- }
-
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- return onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- MenuInflater inflater = mode.getMenuInflater();
- inflater.inflate(R.menu.ingest_menu_item_list_selection, menu);
- updateSelectedTitle(mode);
- mActiveActionMode = mode;
- mActionMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view);
- setSwitcherMenuState(mActionMenuSwitcherItem, mFullscreenPagerVisible);
- return true;
- }
-
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- mActiveActionMode = null;
- mActionMenuSwitcherItem = null;
- mHandler.sendEmptyMessage(ItemListHandler.MSG_BULK_CHECKED_CHANGE);
- }
-
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- updateSelectedTitle(mode);
- return false;
- }
- };
-
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.import_items:
- if (mActiveActionMode != null) {
- mHelperService.importSelectedItems(
- mGridView.getCheckedItemPositions(),
- mAdapter);
- mActiveActionMode.finish();
- }
- return true;
- case R.id.ingest_switch_view:
- setFullscreenPagerVisibility(!mFullscreenPagerVisible);
- return true;
- default:
- return false;
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.ingest_menu_item_list_selection, menu);
- mMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view);
- menu.findItem(R.id.import_items).setVisible(false);
- setSwitcherMenuState(mMenuSwitcherItem, mFullscreenPagerVisible);
- return true;
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- doUnbindHelperService();
- }
-
- @Override
- protected void onResume() {
- DateTileView.refreshLocale();
- mActive = true;
- if (mHelperService != null) mHelperService.setClientActivity(this);
- updateWarningView();
- super.onResume();
- }
-
- @Override
- protected void onPause() {
- if (mHelperService != null) mHelperService.setClientActivity(null);
- mActive = false;
- cleanupProgressDialog();
- super.onPause();
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- MtpBitmapFetch.configureForContext(this);
- }
-
- private void showWarningView(int textResId) {
- if (mWarningView == null) {
- mWarningView = findViewById(R.id.ingest_warning_view);
- mWarningText =
- (TextView)mWarningView.findViewById(R.id.ingest_warning_view_text);
- }
- mWarningText.setText(textResId);
- mWarningView.setVisibility(View.VISIBLE);
- setFullscreenPagerVisibility(false);
- mGridView.setVisibility(View.GONE);
- }
-
- private void hideWarningView() {
- if (mWarningView != null) {
- mWarningView.setVisibility(View.GONE);
- setFullscreenPagerVisibility(false);
- }
- }
-
- private PositionMappingCheckBroker mPositionMappingCheckBroker = new PositionMappingCheckBroker();
-
- private class PositionMappingCheckBroker extends CheckBroker
- implements OnClearChoicesListener {
- private int mLastMappingPager = -1;
- private int mLastMappingGrid = -1;
-
- private int mapPagerToGridPosition(int position) {
- if (position != mLastMappingPager) {
- mLastMappingPager = position;
- mLastMappingGrid = mAdapter.translatePositionWithoutLabels(position);
- }
- return mLastMappingGrid;
- }
-
- private int mapGridToPagerPosition(int position) {
- if (position != mLastMappingGrid) {
- mLastMappingGrid = position;
- mLastMappingPager = mPagerAdapter.translatePositionWithLabels(position);
- }
- return mLastMappingPager;
- }
-
- @Override
- public void setItemChecked(int position, boolean checked) {
- mGridView.setItemChecked(mapPagerToGridPosition(position), checked);
- }
-
- @Override
- public void onCheckedChange(int position, boolean checked) {
- if (mPagerAdapter != null) {
- super.onCheckedChange(mapGridToPagerPosition(position), checked);
- }
- }
-
- @Override
- public boolean isItemChecked(int position) {
- return mGridView.getCheckedItemPositions().get(mapPagerToGridPosition(position));
- }
-
- @Override
- public void onClearChoices() {
- onBulkCheckedChange();
- }
- };
-
- private DataSetObserver mMasterObserver = new DataSetObserver() {
- @Override
- public void onChanged() {
- if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged();
- }
- };
-
- private int pickFullscreenStartingPosition() {
- int firstVisiblePosition = mGridView.getFirstVisiblePosition();
- if (mLastCheckedPosition <= firstVisiblePosition
- || mLastCheckedPosition > mGridView.getLastVisiblePosition()) {
- return firstVisiblePosition;
- } else {
- return mLastCheckedPosition;
- }
- }
-
- private void setSwitcherMenuState(MenuItem menuItem, boolean inFullscreenMode) {
- if (menuItem == null) return;
- if (!inFullscreenMode) {
- menuItem.setIcon(android.R.drawable.ic_menu_zoom);
- menuItem.setTitle(R.string.switch_photo_fullscreen);
- } else {
- menuItem.setIcon(android.R.drawable.ic_dialog_dialer);
- menuItem.setTitle(R.string.switch_photo_grid);
- }
- }
-
- private void setFullscreenPagerVisibility(boolean visible) {
- mFullscreenPagerVisible = visible;
- if (visible) {
- if (mPagerAdapter == null) {
- mPagerAdapter = new MtpPagerAdapter(this, mPositionMappingCheckBroker);
- mPagerAdapter.setMtpDeviceIndex(mAdapter.getMtpDeviceIndex());
- }
- mFullscreenPager.setAdapter(mPagerAdapter);
- mFullscreenPager.setCurrentItem(mPagerAdapter.translatePositionWithLabels(
- pickFullscreenStartingPosition()), false);
- } else if (mPagerAdapter != null) {
- mGridView.setSelection(mAdapter.translatePositionWithoutLabels(
- mFullscreenPager.getCurrentItem()));
- mFullscreenPager.setAdapter(null);
- }
- mGridView.setVisibility(visible ? View.INVISIBLE : View.VISIBLE);
- mFullscreenPager.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
- if (mActionMenuSwitcherItem != null) {
- setSwitcherMenuState(mActionMenuSwitcherItem, visible);
- }
- setSwitcherMenuState(mMenuSwitcherItem, visible);
- }
-
- private void updateWarningView() {
- if (!mAdapter.deviceConnected()) {
- showWarningView(R.string.ingest_no_device);
- } else if (mAdapter.indexReady() && mAdapter.getCount() == 0) {
- showWarningView(R.string.ingest_empty_device);
- } else {
- hideWarningView();
- }
- }
-
- private void UiThreadNotifyIndexChanged() {
- mAdapter.notifyDataSetChanged();
- if (mActiveActionMode != null) {
- mActiveActionMode.finish();
- mActiveActionMode = null;
- }
- updateWarningView();
- }
-
- protected void notifyIndexChanged() {
- mHandler.sendEmptyMessage(ItemListHandler.MSG_NOTIFY_CHANGED);
- }
-
- private static class ProgressState {
- String message;
- String title;
- int current;
- int max;
-
- public void reset() {
- title = null;
- message = null;
- current = 0;
- max = 0;
- }
- }
-
- private ProgressState mProgressState = new ProgressState();
-
- @Override
- public void onObjectIndexed(MtpObjectInfo object, int numVisited) {
- // Not guaranteed to be called on the UI thread
- mProgressState.reset();
- mProgressState.max = 0;
- mProgressState.message = getResources().getQuantityString(
- R.plurals.ingest_number_of_items_scanned, numVisited, numVisited);
- mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE);
- }
-
- @Override
- public void onSorting() {
- // Not guaranteed to be called on the UI thread
- mProgressState.reset();
- mProgressState.max = 0;
- mProgressState.message = getResources().getString(R.string.ingest_sorting);
- mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE);
- }
-
- @Override
- public void onIndexFinish() {
- // Not guaranteed to be called on the UI thread
- mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_HIDE);
- mHandler.sendEmptyMessage(ItemListHandler.MSG_NOTIFY_CHANGED);
- }
-
- @Override
- public void onImportProgress(final int visitedCount, final int totalCount,
- String pathIfSuccessful) {
- // Not guaranteed to be called on the UI thread
- mProgressState.reset();
- mProgressState.max = totalCount;
- mProgressState.current = visitedCount;
- mProgressState.title = getResources().getString(R.string.ingest_importing);
- mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE);
- mHandler.removeMessages(ItemListHandler.MSG_PROGRESS_INDETERMINATE);
- mHandler.sendEmptyMessageDelayed(ItemListHandler.MSG_PROGRESS_INDETERMINATE,
- INDETERMINATE_SWITCH_TIMEOUT_MS);
- }
-
- @Override
- public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported,
- int numVisited) {
- // Not guaranteed to be called on the UI thread
- mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_HIDE);
- mHandler.removeMessages(ItemListHandler.MSG_PROGRESS_INDETERMINATE);
- // TODO: maybe show an extra dialog listing the ones that failed
- // importing, if any?
- }
-
- private ProgressDialog getProgressDialog() {
- if (mProgressDialog == null || !mProgressDialog.isShowing()) {
- mProgressDialog = new ProgressDialog(this);
- mProgressDialog.setCancelable(false);
- }
- return mProgressDialog;
- }
-
- private void updateProgressDialog() {
- ProgressDialog dialog = getProgressDialog();
- boolean indeterminate = (mProgressState.max == 0);
- dialog.setIndeterminate(indeterminate);
- dialog.setProgressStyle(indeterminate ? ProgressDialog.STYLE_SPINNER
- : ProgressDialog.STYLE_HORIZONTAL);
- if (mProgressState.title != null) {
- dialog.setTitle(mProgressState.title);
- }
- if (mProgressState.message != null) {
- dialog.setMessage(mProgressState.message);
- }
- if (!indeterminate) {
- dialog.setProgress(mProgressState.current);
- dialog.setMax(mProgressState.max);
- }
- if (!dialog.isShowing()) {
- dialog.show();
- }
- }
-
- private void makeProgressDialogIndeterminate() {
- ProgressDialog dialog = getProgressDialog();
- dialog.setIndeterminate(true);
- }
-
- private void cleanupProgressDialog() {
- if (mProgressDialog != null) {
- mProgressDialog.hide();
- mProgressDialog = null;
- }
- }
-
- // This is static and uses a WeakReference in order to avoid leaking the Activity
- private static class ItemListHandler extends Handler {
- public static final int MSG_PROGRESS_UPDATE = 0;
- public static final int MSG_PROGRESS_HIDE = 1;
- public static final int MSG_NOTIFY_CHANGED = 2;
- public static final int MSG_BULK_CHECKED_CHANGE = 3;
- public static final int MSG_PROGRESS_INDETERMINATE = 4;
-
- WeakReference<IngestActivity> mParentReference;
-
- public ItemListHandler(IngestActivity parent) {
- super();
- mParentReference = new WeakReference<IngestActivity>(parent);
- }
-
- public void handleMessage(Message message) {
- IngestActivity parent = mParentReference.get();
- if (parent == null || !parent.mActive)
- return;
- switch (message.what) {
- case MSG_PROGRESS_HIDE:
- parent.cleanupProgressDialog();
- break;
- case MSG_PROGRESS_UPDATE:
- parent.updateProgressDialog();
- break;
- case MSG_NOTIFY_CHANGED:
- parent.UiThreadNotifyIndexChanged();
- break;
- case MSG_BULK_CHECKED_CHANGE:
- parent.mPositionMappingCheckBroker.onBulkCheckedChange();
- break;
- case MSG_PROGRESS_INDETERMINATE:
- parent.makeProgressDialogIndeterminate();
- break;
- default:
- break;
- }
- }
- }
-
- private ServiceConnection mHelperServiceConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- mHelperService = ((IngestService.LocalBinder) service).getService();
- mHelperService.setClientActivity(IngestActivity.this);
- MtpDeviceIndex index = mHelperService.getIndex();
- mAdapter.setMtpDeviceIndex(index);
- if (mPagerAdapter != null) mPagerAdapter.setMtpDeviceIndex(index);
- }
-
- public void onServiceDisconnected(ComponentName className) {
- mHelperService = null;
- }
- };
-
- private void doBindHelperService() {
- bindService(new Intent(getApplicationContext(), IngestService.class),
- mHelperServiceConnection, Context.BIND_AUTO_CREATE);
- }
-
- private void doUnbindHelperService() {
- if (mHelperService != null) {
- mHelperService.setClientActivity(null);
- unbindService(mHelperServiceConnection);
- }
- }
-}
diff --git a/src/com/android/gallery3d/ingest/IngestService.java b/src/com/android/gallery3d/ingest/IngestService.java
deleted file mode 100644
index 0ce3ab6a9..000000000
--- a/src/com/android/gallery3d/ingest/IngestService.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest;
-
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.media.MediaScannerConnection;
-import android.media.MediaScannerConnection.MediaScannerConnectionClient;
-import android.mtp.MtpDevice;
-import android.mtp.MtpDeviceInfo;
-import android.mtp.MtpObjectInfo;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.support.v4.app.NotificationCompat;
-import android.util.SparseBooleanArray;
-import android.widget.Adapter;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.app.NotificationIds;
-import com.android.gallery3d.data.MtpClient;
-import com.android.gallery3d.util.BucketNames;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public class IngestService extends Service implements ImportTask.Listener,
- MtpDeviceIndex.ProgressListener, MtpClient.Listener {
-
- public class LocalBinder extends Binder {
- IngestService getService() {
- return IngestService.this;
- }
- }
-
- private static final int PROGRESS_UPDATE_INTERVAL_MS = 180;
-
- private static MtpClient sClient;
-
- private final IBinder mBinder = new LocalBinder();
- private ScannerClient mScannerClient;
- private MtpDevice mDevice;
- private String mDevicePrettyName;
- private MtpDeviceIndex mIndex;
- private IngestActivity mClientActivity;
- private boolean mRedeliverImportFinish = false;
- private int mRedeliverImportFinishCount = 0;
- private Collection<MtpObjectInfo> mRedeliverObjectsNotImported;
- private boolean mRedeliverNotifyIndexChanged = false;
- private boolean mRedeliverIndexFinish = false;
- private NotificationManager mNotificationManager;
- private NotificationCompat.Builder mNotificationBuilder;
- private long mLastProgressIndexTime = 0;
- private boolean mNeedRelaunchNotification = false;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mScannerClient = new ScannerClient(this);
- mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- mNotificationBuilder = new NotificationCompat.Builder(this);
- mNotificationBuilder.setSmallIcon(android.R.drawable.stat_notify_sync) // TODO drawable
- .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, IngestActivity.class), 0));
- mIndex = MtpDeviceIndex.getInstance();
- mIndex.setProgressListener(this);
-
- if (sClient == null) {
- sClient = new MtpClient(getApplicationContext());
- }
- List<MtpDevice> devices = sClient.getDeviceList();
- if (devices.size() > 0) {
- setDevice(devices.get(0));
- }
- sClient.addListener(this);
- }
-
- @Override
- public void onDestroy() {
- sClient.removeListener(this);
- mIndex.unsetProgressListener(this);
- super.onDestroy();
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- private void setDevice(MtpDevice device) {
- if (mDevice == device) return;
- mRedeliverImportFinish = false;
- mRedeliverObjectsNotImported = null;
- mRedeliverNotifyIndexChanged = false;
- mRedeliverIndexFinish = false;
- mDevice = device;
- mIndex.setDevice(mDevice);
- if (mDevice != null) {
- MtpDeviceInfo deviceInfo = mDevice.getDeviceInfo();
- if (deviceInfo == null) {
- setDevice(null);
- return;
- } else {
- mDevicePrettyName = deviceInfo.getModel();
- mNotificationBuilder.setContentTitle(mDevicePrettyName);
- new Thread(mIndex.getIndexRunnable()).start();
- }
- } else {
- mDevicePrettyName = null;
- }
- if (mClientActivity != null) {
- mClientActivity.notifyIndexChanged();
- } else {
- mRedeliverNotifyIndexChanged = true;
- }
- }
-
- protected MtpDeviceIndex getIndex() {
- return mIndex;
- }
-
- protected void setClientActivity(IngestActivity activity) {
- if (mClientActivity == activity) return;
- mClientActivity = activity;
- if (mClientActivity == null) {
- if (mNeedRelaunchNotification) {
- mNotificationBuilder.setProgress(0, 0, false)
- .setContentText(getResources().getText(R.string.ingest_scanning_done));
- mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
- mNotificationBuilder.build());
- }
- return;
- }
- mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_IMPORTING);
- mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING);
- if (mRedeliverImportFinish) {
- mClientActivity.onImportFinish(mRedeliverObjectsNotImported,
- mRedeliverImportFinishCount);
- mRedeliverImportFinish = false;
- mRedeliverObjectsNotImported = null;
- }
- if (mRedeliverNotifyIndexChanged) {
- mClientActivity.notifyIndexChanged();
- mRedeliverNotifyIndexChanged = false;
- }
- if (mRedeliverIndexFinish) {
- mClientActivity.onIndexFinish();
- mRedeliverIndexFinish = false;
- }
- }
-
- protected void importSelectedItems(SparseBooleanArray selected, Adapter adapter) {
- List<MtpObjectInfo> importHandles = new ArrayList<MtpObjectInfo>();
- for (int i = 0; i < selected.size(); i++) {
- if (selected.valueAt(i)) {
- Object item = adapter.getItem(selected.keyAt(i));
- if (item instanceof MtpObjectInfo) {
- importHandles.add(((MtpObjectInfo) item));
- }
- }
- }
- ImportTask task = new ImportTask(mDevice, importHandles, BucketNames.IMPORTED, this);
- task.setListener(this);
- mNotificationBuilder.setProgress(0, 0, true)
- .setContentText(getResources().getText(R.string.ingest_importing));
- startForeground(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
- mNotificationBuilder.build());
- new Thread(task).start();
- }
-
- @Override
- public void deviceAdded(MtpDevice device) {
- if (mDevice == null) {
- setDevice(device);
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER,
- "DeviceConnected", null);
- }
- }
-
- @Override
- public void deviceRemoved(MtpDevice device) {
- if (device == mDevice) {
- setDevice(null);
- mNeedRelaunchNotification = false;
- mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING);
- }
- }
-
- @Override
- public void onImportProgress(int visitedCount, int totalCount,
- String pathIfSuccessful) {
- if (pathIfSuccessful != null) {
- mScannerClient.scanPath(pathIfSuccessful);
- }
- mNeedRelaunchNotification = false;
- if (mClientActivity != null) {
- mClientActivity.onImportProgress(visitedCount, totalCount, pathIfSuccessful);
- }
- mNotificationBuilder.setProgress(totalCount, visitedCount, false)
- .setContentText(getResources().getText(R.string.ingest_importing));
- mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
- mNotificationBuilder.build());
- }
-
- @Override
- public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported,
- int visitedCount) {
- stopForeground(true);
- mNeedRelaunchNotification = true;
- if (mClientActivity != null) {
- mClientActivity.onImportFinish(objectsNotImported, visitedCount);
- } else {
- mRedeliverImportFinish = true;
- mRedeliverObjectsNotImported = objectsNotImported;
- mRedeliverImportFinishCount = visitedCount;
- mNotificationBuilder.setProgress(0, 0, false)
- .setContentText(getResources().getText(R.string.import_complete));
- mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
- mNotificationBuilder.build());
- }
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER,
- "ImportFinished", null, visitedCount);
- }
-
- @Override
- public void onObjectIndexed(MtpObjectInfo object, int numVisited) {
- mNeedRelaunchNotification = false;
- if (mClientActivity != null) {
- mClientActivity.onObjectIndexed(object, numVisited);
- } else {
- // Throttle the updates to one every PROGRESS_UPDATE_INTERVAL_MS milliseconds
- long currentTime = SystemClock.uptimeMillis();
- if (currentTime > mLastProgressIndexTime + PROGRESS_UPDATE_INTERVAL_MS) {
- mLastProgressIndexTime = currentTime;
- mNotificationBuilder.setProgress(0, numVisited, true)
- .setContentText(getResources().getText(R.string.ingest_scanning));
- mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
- mNotificationBuilder.build());
- }
- }
- }
-
- @Override
- public void onSorting() {
- if (mClientActivity != null) mClientActivity.onSorting();
- }
-
- @Override
- public void onIndexFinish() {
- mNeedRelaunchNotification = true;
- if (mClientActivity != null) {
- mClientActivity.onIndexFinish();
- } else {
- mNotificationBuilder.setProgress(0, 0, false)
- .setContentText(getResources().getText(R.string.ingest_scanning_done));
- mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
- mNotificationBuilder.build());
- mRedeliverIndexFinish = true;
- }
- }
-
- // Copied from old Gallery3d code
- private static final class ScannerClient implements MediaScannerConnectionClient {
- ArrayList<String> mPaths = new ArrayList<String>();
- MediaScannerConnection mScannerConnection;
- boolean mConnected;
- Object mLock = new Object();
-
- public ScannerClient(Context context) {
- mScannerConnection = new MediaScannerConnection(context, this);
- }
-
- public void scanPath(String path) {
- synchronized (mLock) {
- if (mConnected) {
- mScannerConnection.scanFile(path, null);
- } else {
- mPaths.add(path);
- mScannerConnection.connect();
- }
- }
- }
-
- @Override
- public void onMediaScannerConnected() {
- synchronized (mLock) {
- mConnected = true;
- if (!mPaths.isEmpty()) {
- for (String path : mPaths) {
- mScannerConnection.scanFile(path, null);
- }
- mPaths.clear();
- }
- }
- }
-
- @Override
- public void onScanCompleted(String path, Uri uri) {
- }
- }
-}
diff --git a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java b/src/com/android/gallery3d/ingest/MtpDeviceIndex.java
deleted file mode 100644
index d30f94a87..000000000
--- a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest;
-
-import android.mtp.MtpConstants;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-
-/**
- * MTP objects in the index are organized into "buckets," or groupings.
- * At present, these buckets are based on the date an item was created.
- *
- * When the index is created, the buckets are sorted in their natural
- * order, and the items within the buckets sorted by the date they are taken.
- *
- * The index enables the access of items and bucket labels as one unified list.
- * For example, let's say we have the following data in the index:
- * [Bucket A]: [photo 1], [photo 2]
- * [Bucket B]: [photo 3]
- *
- * Then the items can be thought of as being organized as a 5 element list:
- * [Bucket A], [photo 1], [photo 2], [Bucket B], [photo 3]
- *
- * The data can also be accessed in descending order, in which case the list
- * would be a bit different from simply reversing the ascending list, since the
- * bucket labels need to always be at the beginning:
- * [Bucket B], [photo 3], [Bucket A], [photo 2], [photo 1]
- *
- * The index enables all the following operations in constant time, both for
- * ascending and descending views of the data:
- * - get/getAscending/getDescending: get an item at a specified list position
- * - size: get the total number of items (bucket labels and MTP objects)
- * - getFirstPositionForBucketNumber
- * - getBucketNumberForPosition
- * - isFirstInBucket
- *
- * See the comments in buildLookupIndex for implementation notes.
- */
-public class MtpDeviceIndex {
-
- public static final int FORMAT_MOV = 0x300D; // For some reason this is not in MtpConstants
-
- public static final Set<Integer> SUPPORTED_IMAGE_FORMATS;
- public static final Set<Integer> SUPPORTED_VIDEO_FORMATS;
-
- static {
- SUPPORTED_IMAGE_FORMATS = new HashSet<Integer>();
- SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_JFIF);
- SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_EXIF_JPEG);
- SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_PNG);
- SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_GIF);
- SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_BMP);
-
- SUPPORTED_VIDEO_FORMATS = new HashSet<Integer>();
- SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_3GP_CONTAINER);
- SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_AVI);
- SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_MP4_CONTAINER);
- SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_MPEG);
- // TODO: add FORMAT_MOV once Media Scanner supports .mov files
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((mDevice == null) ? 0 : mDevice.getDeviceId());
- result = prime * result + mGeneration;
- return result;
- }
-
- public interface ProgressListener {
- public void onObjectIndexed(MtpObjectInfo object, int numVisited);
-
- public void onSorting();
-
- public void onIndexFinish();
- }
-
- public enum SortOrder {
- Ascending, Descending
- }
-
- private MtpDevice mDevice;
- private int[] mUnifiedLookupIndex;
- private MtpObjectInfo[] mMtpObjects;
- private DateBucket[] mBuckets;
- private int mGeneration = 0;
-
- public enum Progress {
- Uninitialized, Initialized, Pending, Started, Sorting, Finished
- }
-
- private Progress mProgress = Progress.Uninitialized;
- private ProgressListener mProgressListener;
-
- private static final MtpDeviceIndex sInstance = new MtpDeviceIndex();
- private static final MtpObjectTimestampComparator sMtpObjectComparator =
- new MtpObjectTimestampComparator();
-
- public static MtpDeviceIndex getInstance() {
- return sInstance;
- }
-
- private MtpDeviceIndex() {
- }
-
- synchronized public MtpDevice getDevice() {
- return mDevice;
- }
-
- /**
- * Sets the MtpDevice that should be indexed and initializes state, but does
- * not kick off the actual indexing task, which is instead done by using
- * {@link #getIndexRunnable()}
- *
- * @param device The MtpDevice that should be indexed
- */
- synchronized public void setDevice(MtpDevice device) {
- if (device == mDevice) return;
- mDevice = device;
- resetState();
- }
-
- /**
- * Provides a Runnable for the indexing task assuming the state has already
- * been correctly initialized (by calling {@link #setDevice(MtpDevice)}) and
- * has not already been run.
- *
- * @return Runnable for the main indexing task
- */
- synchronized public Runnable getIndexRunnable() {
- if (mProgress != Progress.Initialized) return null;
- mProgress = Progress.Pending;
- return new IndexRunnable(mDevice);
- }
-
- synchronized public boolean indexReady() {
- return mProgress == Progress.Finished;
- }
-
- synchronized public Progress getProgress() {
- return mProgress;
- }
-
- /**
- * @param listener Listener to change to
- * @return Progress at the time the listener was added (useful for
- * configuring initial UI state)
- */
- synchronized public Progress setProgressListener(ProgressListener listener) {
- mProgressListener = listener;
- return mProgress;
- }
-
- /**
- * Make the listener null if it matches the argument
- *
- * @param listener Listener to unset, if currently registered
- */
- synchronized public void unsetProgressListener(ProgressListener listener) {
- if (mProgressListener == listener)
- mProgressListener = null;
- }
-
- /**
- * @return The total number of elements in the index (labels and items)
- */
- public int size() {
- return mProgress == Progress.Finished ? mUnifiedLookupIndex.length : 0;
- }
-
- /**
- * @param position Index of item to fetch, where 0 is the first item in the
- * specified order
- * @param order
- * @return the bucket label or MtpObjectInfo at the specified position and
- * order
- */
- public Object get(int position, SortOrder order) {
- if (mProgress != Progress.Finished) return null;
- if(order == SortOrder.Ascending) {
- DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]];
- if (bucket.unifiedStartIndex == position) {
- return bucket.bucket;
- } else {
- return mMtpObjects[bucket.itemsStartIndex + position - 1
- - bucket.unifiedStartIndex];
- }
- } else {
- int zeroIndex = mUnifiedLookupIndex.length - 1 - position;
- DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]];
- if (bucket.unifiedEndIndex == zeroIndex) {
- return bucket.bucket;
- } else {
- return mMtpObjects[bucket.itemsStartIndex + zeroIndex
- - bucket.unifiedStartIndex];
- }
- }
- }
-
- /**
- * @param position Index of item to fetch from a view of the data that doesn't
- * include labels and is in the specified order
- * @return position-th item in specified order, when not including labels
- */
- public MtpObjectInfo getWithoutLabels(int position, SortOrder order) {
- if (mProgress != Progress.Finished) return null;
- if (order == SortOrder.Ascending) {
- return mMtpObjects[position];
- } else {
- return mMtpObjects[mMtpObjects.length - 1 - position];
- }
- }
-
- /**
- * Although this is O(log(number of buckets)), and thus should not be used
- * in hotspots, even if the attached device has items for every day for
- * a five-year timeframe, it would still only take 11 iterations at most,
- * so shouldn't be a huge issue.
- * @param position Index of item to map from a view of the data that doesn't
- * include labels and is in the specified order
- * @param order
- * @return position in a view of the data that does include labels
- */
- public int getPositionFromPositionWithoutLabels(int position, SortOrder order) {
- if (mProgress != Progress.Finished) return -1;
- if (order == SortOrder.Descending) {
- position = mMtpObjects.length - 1 - position;
- }
- int bucketNumber = 0;
- int iMin = 0;
- int iMax = mBuckets.length - 1;
- while (iMax >= iMin) {
- int iMid = (iMax + iMin) / 2;
- if (mBuckets[iMid].itemsStartIndex + mBuckets[iMid].numItems <= position) {
- iMin = iMid + 1;
- } else if (mBuckets[iMid].itemsStartIndex > position) {
- iMax = iMid - 1;
- } else {
- bucketNumber = iMid;
- break;
- }
- }
- int mappedPos = mBuckets[bucketNumber].unifiedStartIndex
- + position - mBuckets[bucketNumber].itemsStartIndex;
- if (order == SortOrder.Descending) {
- mappedPos = mUnifiedLookupIndex.length - 1 - mappedPos;
- }
- return mappedPos;
- }
-
- public int getPositionWithoutLabelsFromPosition(int position, SortOrder order) {
- if (mProgress != Progress.Finished) return -1;
- if(order == SortOrder.Ascending) {
- DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]];
- if (bucket.unifiedStartIndex == position) position++;
- return bucket.itemsStartIndex + position - 1 - bucket.unifiedStartIndex;
- } else {
- int zeroIndex = mUnifiedLookupIndex.length - 1 - position;
- DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]];
- if (bucket.unifiedEndIndex == zeroIndex) zeroIndex--;
- return mMtpObjects.length - 1 - bucket.itemsStartIndex
- - zeroIndex + bucket.unifiedStartIndex;
- }
- }
-
- /**
- * @return The number of MTP items in the index (without labels)
- */
- public int sizeWithoutLabels() {
- return mProgress == Progress.Finished ? mMtpObjects.length : 0;
- }
-
- public int getFirstPositionForBucketNumber(int bucketNumber, SortOrder order) {
- if (order == SortOrder.Ascending) {
- return mBuckets[bucketNumber].unifiedStartIndex;
- } else {
- return mUnifiedLookupIndex.length - mBuckets[mBuckets.length - 1 - bucketNumber].unifiedEndIndex - 1;
- }
- }
-
- public int getBucketNumberForPosition(int position, SortOrder order) {
- if (order == SortOrder.Ascending) {
- return mUnifiedLookupIndex[position];
- } else {
- return mBuckets.length - 1 - mUnifiedLookupIndex[mUnifiedLookupIndex.length - 1 - position];
- }
- }
-
- public boolean isFirstInBucket(int position, SortOrder order) {
- if (order == SortOrder.Ascending) {
- return mBuckets[mUnifiedLookupIndex[position]].unifiedStartIndex == position;
- } else {
- position = mUnifiedLookupIndex.length - 1 - position;
- return mBuckets[mUnifiedLookupIndex[position]].unifiedEndIndex == position;
- }
- }
-
- private Object[] mCachedReverseBuckets;
-
- public Object[] getBuckets(SortOrder order) {
- if (mBuckets == null) return null;
- if (order == SortOrder.Ascending) {
- return mBuckets;
- } else {
- if (mCachedReverseBuckets == null) {
- computeReversedBuckets();
- }
- return mCachedReverseBuckets;
- }
- }
-
- /*
- * See the comments for buildLookupIndex for notes on the specific fields of
- * this class.
- */
- private class DateBucket implements Comparable<DateBucket> {
- SimpleDate bucket;
- List<MtpObjectInfo> tempElementsList = new ArrayList<MtpObjectInfo>();
- int unifiedStartIndex;
- int unifiedEndIndex;
- int itemsStartIndex;
- int numItems;
-
- public DateBucket(SimpleDate bucket) {
- this.bucket = bucket;
- }
-
- public DateBucket(SimpleDate bucket, MtpObjectInfo firstElement) {
- this(bucket);
- tempElementsList.add(firstElement);
- }
-
- void sortElements(Comparator<MtpObjectInfo> comparator) {
- Collections.sort(tempElementsList, comparator);
- }
-
- @Override
- public String toString() {
- return bucket.toString();
- }
-
- @Override
- public int hashCode() {
- return bucket.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (!(obj instanceof DateBucket)) return false;
- DateBucket other = (DateBucket) obj;
- if (bucket == null) {
- if (other.bucket != null) return false;
- } else if (!bucket.equals(other.bucket)) {
- return false;
- }
- return true;
- }
-
- @Override
- public int compareTo(DateBucket another) {
- return this.bucket.compareTo(another.bucket);
- }
- }
-
- /**
- * Comparator to sort MtpObjectInfo objects by date created.
- */
- private static class MtpObjectTimestampComparator implements Comparator<MtpObjectInfo> {
- @Override
- public int compare(MtpObjectInfo o1, MtpObjectInfo o2) {
- long diff = o1.getDateCreated() - o2.getDateCreated();
- if (diff < 0) {
- return -1;
- } else if (diff == 0) {
- return 0;
- } else {
- return 1;
- }
- }
- }
-
- private void resetState() {
- mGeneration++;
- mUnifiedLookupIndex = null;
- mMtpObjects = null;
- mBuckets = null;
- mCachedReverseBuckets = null;
- mProgress = (mDevice == null) ? Progress.Uninitialized : Progress.Initialized;
- }
-
-
- private class IndexRunnable implements Runnable {
- private int[] mUnifiedLookupIndex;
- private MtpObjectInfo[] mMtpObjects;
- private DateBucket[] mBuckets;
- private Map<SimpleDate, DateBucket> mBucketsTemp;
- private MtpDevice mDevice;
- private int mNumObjects = 0;
-
- private class IndexingException extends Exception {};
-
- public IndexRunnable(MtpDevice device) {
- mDevice = device;
- }
-
- /*
- * Implementation note: this is the way the index supports a lot of its operations in
- * constant time and respecting the need to have bucket names always come before items
- * in that bucket when accessing the list sequentially, both in ascending and descending
- * orders.
- *
- * Let's say the data we have in the index is the following:
- * [Bucket A]: [photo 1], [photo 2]
- * [Bucket B]: [photo 3]
- *
- * In this case, the lookup index array would be
- * [0, 0, 0, 1, 1]
- *
- * Now, whether we access the list in ascending or descending order, we know which bucket
- * to look in (0 corresponds to A and 1 to B), and can return the bucket label as the first
- * item in a bucket as needed. The individual IndexBUckets have a startIndex and endIndex
- * that correspond to indices in this lookup index array, allowing us to calculate the
- * offset of the specific item we want from within a specific bucket.
- */
- private void buildLookupIndex() {
- int numBuckets = mBuckets.length;
- mUnifiedLookupIndex = new int[mNumObjects + numBuckets];
- int currentUnifiedIndexEntry = 0;
- int nextUnifiedEntry;
-
- mMtpObjects = new MtpObjectInfo[mNumObjects];
- int currentItemsEntry = 0;
- for (int i = 0; i < numBuckets; i++) {
- DateBucket bucket = mBuckets[i];
- nextUnifiedEntry = currentUnifiedIndexEntry + bucket.tempElementsList.size() + 1;
- Arrays.fill(mUnifiedLookupIndex, currentUnifiedIndexEntry, nextUnifiedEntry, i);
- bucket.unifiedStartIndex = currentUnifiedIndexEntry;
- bucket.unifiedEndIndex = nextUnifiedEntry - 1;
- currentUnifiedIndexEntry = nextUnifiedEntry;
-
- bucket.itemsStartIndex = currentItemsEntry;
- bucket.numItems = bucket.tempElementsList.size();
- for (int j = 0; j < bucket.numItems; j++) {
- mMtpObjects[currentItemsEntry] = bucket.tempElementsList.get(j);
- currentItemsEntry++;
- }
- bucket.tempElementsList = null;
- }
- }
-
- private void copyResults() {
- MtpDeviceIndex.this.mUnifiedLookupIndex = mUnifiedLookupIndex;
- MtpDeviceIndex.this.mMtpObjects = mMtpObjects;
- MtpDeviceIndex.this.mBuckets = mBuckets;
- mUnifiedLookupIndex = null;
- mMtpObjects = null;
- mBuckets = null;
- }
-
- @Override
- public void run() {
- try {
- indexDevice();
- } catch (IndexingException e) {
- synchronized (MtpDeviceIndex.this) {
- resetState();
- if (mProgressListener != null) {
- mProgressListener.onIndexFinish();
- }
- }
- }
- }
-
- private void indexDevice() throws IndexingException {
- synchronized (MtpDeviceIndex.this) {
- mProgress = Progress.Started;
- }
- mBucketsTemp = new HashMap<SimpleDate, DateBucket>();
- for (int storageId : mDevice.getStorageIds()) {
- if (mDevice != getDevice()) throw new IndexingException();
- Stack<Integer> pendingDirectories = new Stack<Integer>();
- pendingDirectories.add(0xFFFFFFFF); // start at the root of the device
- while (!pendingDirectories.isEmpty()) {
- if (mDevice != getDevice()) throw new IndexingException();
- int dirHandle = pendingDirectories.pop();
- for (int objectHandle : mDevice.getObjectHandles(storageId, 0, dirHandle)) {
- MtpObjectInfo objectInfo = mDevice.getObjectInfo(objectHandle);
- if (objectInfo == null) throw new IndexingException();
- int format = objectInfo.getFormat();
- if (format == MtpConstants.FORMAT_ASSOCIATION) {
- pendingDirectories.add(objectHandle);
- } else if (SUPPORTED_IMAGE_FORMATS.contains(format)
- || SUPPORTED_VIDEO_FORMATS.contains(format)) {
- addObject(objectInfo);
- }
- }
- }
- }
- Collection<DateBucket> values = mBucketsTemp.values();
- mBucketsTemp = null;
- mBuckets = values.toArray(new DateBucket[values.size()]);
- values = null;
- synchronized (MtpDeviceIndex.this) {
- mProgress = Progress.Sorting;
- if (mProgressListener != null) {
- mProgressListener.onSorting();
- }
- }
- sortAll();
- buildLookupIndex();
- synchronized (MtpDeviceIndex.this) {
- if (mDevice != getDevice()) throw new IndexingException();
- copyResults();
-
- /*
- * In order for getBuckets to operate in constant time for descending
- * order, we must precompute a reversed array of the buckets, mainly
- * because the android.widget.SectionIndexer interface which adapters
- * that call getBuckets implement depends on section numbers to be
- * ascending relative to the scroll position, so we must have this for
- * descending order or the scrollbar goes crazy.
- */
- computeReversedBuckets();
-
- mProgress = Progress.Finished;
- if (mProgressListener != null) {
- mProgressListener.onIndexFinish();
- }
- }
- }
-
- private SimpleDate mDateInstance = new SimpleDate();
-
- private void addObject(MtpObjectInfo objectInfo) {
- mNumObjects++;
- mDateInstance.setTimestamp(objectInfo.getDateCreated());
- DateBucket bucket = mBucketsTemp.get(mDateInstance);
- if (bucket == null) {
- bucket = new DateBucket(mDateInstance, objectInfo);
- mBucketsTemp.put(mDateInstance, bucket);
- mDateInstance = new SimpleDate(); // only create new date
- // objects when they are used
- return;
- } else {
- bucket.tempElementsList.add(objectInfo);
- }
- if (mProgressListener != null) {
- mProgressListener.onObjectIndexed(objectInfo, mNumObjects);
- }
- }
-
- private void sortAll() {
- Arrays.sort(mBuckets);
- for (DateBucket bucket : mBuckets) {
- bucket.sortElements(sMtpObjectComparator);
- }
- }
-
- }
-
- private void computeReversedBuckets() {
- mCachedReverseBuckets = new Object[mBuckets.length];
- for (int i = 0; i < mCachedReverseBuckets.length; i++) {
- mCachedReverseBuckets[i] = mBuckets[mBuckets.length - 1 - i];
- }
- }
-}
diff --git a/src/com/android/gallery3d/ingest/SimpleDate.java b/src/com/android/gallery3d/ingest/SimpleDate.java
deleted file mode 100644
index 05db2cde2..000000000
--- a/src/com/android/gallery3d/ingest/SimpleDate.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest;
-
-import java.text.DateFormat;
-import java.util.Calendar;
-
-/**
- * Represents a date (year, month, day)
- */
-public class SimpleDate implements Comparable<SimpleDate> {
- public int month; // MM
- public int day; // DD
- public int year; // YYYY
- private long timestamp;
- private String mCachedStringRepresentation;
-
- public SimpleDate() {
- }
-
- public SimpleDate(long timestamp) {
- setTimestamp(timestamp);
- }
-
- private static Calendar sCalendarInstance = Calendar.getInstance();
-
- public void setTimestamp(long timestamp) {
- synchronized (sCalendarInstance) {
- // TODO find a more efficient way to convert a timestamp to a date?
- sCalendarInstance.setTimeInMillis(timestamp);
- this.day = sCalendarInstance.get(Calendar.DATE);
- this.month = sCalendarInstance.get(Calendar.MONTH);
- this.year = sCalendarInstance.get(Calendar.YEAR);
- this.timestamp = timestamp;
- mCachedStringRepresentation = DateFormat.getDateInstance(DateFormat.SHORT).format(timestamp);
- }
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + day;
- result = prime * result + month;
- result = prime * result + year;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (!(obj instanceof SimpleDate))
- return false;
- SimpleDate other = (SimpleDate) obj;
- if (year != other.year)
- return false;
- if (month != other.month)
- return false;
- if (day != other.day)
- return false;
- return true;
- }
-
- @Override
- public int compareTo(SimpleDate other) {
- int yearDiff = this.year - other.getYear();
- if (yearDiff != 0)
- return yearDiff;
- else {
- int monthDiff = this.month - other.getMonth();
- if (monthDiff != 0)
- return monthDiff;
- else
- return this.day - other.getDay();
- }
- }
-
- public int getDay() {
- return day;
- }
-
- public int getMonth() {
- return month;
- }
-
- public int getYear() {
- return year;
- }
-
- @Override
- public String toString() {
- if (mCachedStringRepresentation == null) {
- mCachedStringRepresentation = DateFormat.getDateInstance(DateFormat.SHORT).format(timestamp);
- }
- return mCachedStringRepresentation;
- }
-}
diff --git a/src/com/android/gallery3d/ingest/adapter/CheckBroker.java b/src/com/android/gallery3d/ingest/adapter/CheckBroker.java
deleted file mode 100644
index 6783f23c5..000000000
--- a/src/com/android/gallery3d/ingest/adapter/CheckBroker.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.adapter;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-public abstract class CheckBroker {
- private Collection<OnCheckedChangedListener> mListeners =
- new ArrayList<OnCheckedChangedListener>();
-
- public interface OnCheckedChangedListener {
- public void onCheckedChanged(int position, boolean isChecked);
- public void onBulkCheckedChanged();
- }
-
- public abstract void setItemChecked(int position, boolean checked);
-
- public void onCheckedChange(int position, boolean checked) {
- if (isItemChecked(position) != checked) {
- for (OnCheckedChangedListener l : mListeners) {
- l.onCheckedChanged(position, checked);
- }
- }
- }
-
- public void onBulkCheckedChange() {
- for (OnCheckedChangedListener l : mListeners) {
- l.onBulkCheckedChanged();
- }
- }
-
- public abstract boolean isItemChecked(int position);
-
- public void registerOnCheckedChangeListener(OnCheckedChangedListener l) {
- mListeners.add(l);
- }
-
- public void unregisterOnCheckedChangeListener(OnCheckedChangedListener l) {
- mListeners.remove(l);
- }
-}
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
deleted file mode 100644
index e8dd69f8c..000000000
--- a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.adapter;
-
-import android.app.Activity;
-import android.content.Context;
-import android.mtp.MtpObjectInfo;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.SectionIndexer;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.MtpDeviceIndex;
-import com.android.gallery3d.ingest.MtpDeviceIndex.SortOrder;
-import com.android.gallery3d.ingest.SimpleDate;
-import com.android.gallery3d.ingest.ui.DateTileView;
-import com.android.gallery3d.ingest.ui.MtpThumbnailTileView;
-
-public class MtpAdapter extends BaseAdapter implements SectionIndexer {
- public static final int ITEM_TYPE_MEDIA = 0;
- public static final int ITEM_TYPE_BUCKET = 1;
-
- private Context mContext;
- private MtpDeviceIndex mModel;
- private SortOrder mSortOrder = SortOrder.Descending;
- private LayoutInflater mInflater;
- private int mGeneration = 0;
-
- public MtpAdapter(Activity context) {
- super();
- mContext = context;
- mInflater = LayoutInflater.from(context);
- }
-
- public void setMtpDeviceIndex(MtpDeviceIndex index) {
- mModel = index;
- notifyDataSetChanged();
- }
-
- public MtpDeviceIndex getMtpDeviceIndex() {
- return mModel;
- }
-
- @Override
- public void notifyDataSetChanged() {
- mGeneration++;
- super.notifyDataSetChanged();
- }
-
- @Override
- public void notifyDataSetInvalidated() {
- mGeneration++;
- super.notifyDataSetInvalidated();
- }
-
- public boolean deviceConnected() {
- return (mModel != null) && (mModel.getDevice() != null);
- }
-
- public boolean indexReady() {
- return (mModel != null) && mModel.indexReady();
- }
-
- @Override
- public int getCount() {
- return mModel != null ? mModel.size() : 0;
- }
-
- @Override
- public Object getItem(int position) {
- return mModel.get(position, mSortOrder);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- @Override
- public boolean isEnabled(int position) {
- return true;
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public int getViewTypeCount() {
- return 2;
- }
-
- @Override
- public int getItemViewType(int position) {
- // If the position is the first in its section, then it corresponds to
- // a title tile, if not it's a media tile
- if (position == getPositionForSection(getSectionForPosition(position))) {
- return ITEM_TYPE_BUCKET;
- } else {
- return ITEM_TYPE_MEDIA;
- }
- }
-
- public boolean itemAtPositionIsBucket(int position) {
- return getItemViewType(position) == ITEM_TYPE_BUCKET;
- }
-
- public boolean itemAtPositionIsMedia(int position) {
- return getItemViewType(position) == ITEM_TYPE_MEDIA;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- int type = getItemViewType(position);
- if (type == ITEM_TYPE_MEDIA) {
- MtpThumbnailTileView imageView;
- if (convertView == null) {
- imageView = (MtpThumbnailTileView) mInflater.inflate(
- R.layout.ingest_thumbnail, parent, false);
- } else {
- imageView = (MtpThumbnailTileView) convertView;
- }
- imageView.setMtpDeviceAndObjectInfo(mModel.getDevice(), (MtpObjectInfo)getItem(position), mGeneration);
- return imageView;
- } else {
- DateTileView dateTile;
- if (convertView == null) {
- dateTile = (DateTileView) mInflater.inflate(
- R.layout.ingest_date_tile, parent, false);
- } else {
- dateTile = (DateTileView) convertView;
- }
- dateTile.setDate((SimpleDate)getItem(position));
- return dateTile;
- }
- }
-
- @Override
- public int getPositionForSection(int section) {
- if (getCount() == 0) {
- return 0;
- }
- int numSections = getSections().length;
- if (section >= numSections) {
- section = numSections - 1;
- }
- return mModel.getFirstPositionForBucketNumber(section, mSortOrder);
- }
-
- @Override
- public int getSectionForPosition(int position) {
- int count = getCount();
- if (count == 0) {
- return 0;
- }
- if (position >= count) {
- position = count - 1;
- }
- return mModel.getBucketNumberForPosition(position, mSortOrder);
- }
-
- @Override
- public Object[] getSections() {
- return getCount() > 0 ? mModel.getBuckets(mSortOrder) : null;
- }
-
- public SortOrder getSortOrder() {
- return mSortOrder;
- }
-
- public int translatePositionWithoutLabels(int position) {
- if (mModel == null) return -1;
- return mModel.getPositionFromPositionWithoutLabels(position, mSortOrder);
- }
-}
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
deleted file mode 100644
index 9e7abc01d..000000000
--- a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.adapter;
-
-import android.content.Context;
-import android.mtp.MtpObjectInfo;
-import android.support.v4.view.PagerAdapter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.MtpDeviceIndex;
-import com.android.gallery3d.ingest.MtpDeviceIndex.SortOrder;
-import com.android.gallery3d.ingest.ui.MtpFullscreenView;
-
-public class MtpPagerAdapter extends PagerAdapter {
-
- private LayoutInflater mInflater;
- private int mGeneration = 0;
- private CheckBroker mBroker;
- private MtpDeviceIndex mModel;
- private SortOrder mSortOrder = SortOrder.Descending;
-
- private MtpFullscreenView mReusableView = null;
-
- public MtpPagerAdapter(Context context, CheckBroker broker) {
- super();
- mInflater = LayoutInflater.from(context);
- mBroker = broker;
- }
-
- public void setMtpDeviceIndex(MtpDeviceIndex index) {
- mModel = index;
- notifyDataSetChanged();
- }
-
- @Override
- public int getCount() {
- return mModel != null ? mModel.sizeWithoutLabels() : 0;
- }
-
- @Override
- public void notifyDataSetChanged() {
- mGeneration++;
- super.notifyDataSetChanged();
- }
-
- public int translatePositionWithLabels(int position) {
- if (mModel == null) return -1;
- return mModel.getPositionWithoutLabelsFromPosition(position, mSortOrder);
- }
-
- @Override
- public void finishUpdate(ViewGroup container) {
- mReusableView = null;
- super.finishUpdate(container);
- }
-
- @Override
- public boolean isViewFromObject(View view, Object object) {
- return view == object;
- }
-
- @Override
- public void destroyItem(ViewGroup container, int position, Object object) {
- MtpFullscreenView v = (MtpFullscreenView)object;
- container.removeView(v);
- mBroker.unregisterOnCheckedChangeListener(v);
- mReusableView = v;
- }
-
- @Override
- public Object instantiateItem(ViewGroup container, int position) {
- MtpFullscreenView v;
- if (mReusableView != null) {
- v = mReusableView;
- mReusableView = null;
- } else {
- v = (MtpFullscreenView) mInflater.inflate(R.layout.ingest_fullsize, container, false);
- }
- MtpObjectInfo i = mModel.getWithoutLabels(position, mSortOrder);
- v.getImageView().setMtpDeviceAndObjectInfo(mModel.getDevice(), i, mGeneration);
- v.setPositionAndBroker(position, mBroker);
- container.addView(v);
- return v;
- }
-}
diff --git a/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java b/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java
deleted file mode 100644
index bbc90f670..000000000
--- a/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.data;
-
-import android.graphics.Bitmap;
-
-public class BitmapWithMetadata {
- public Bitmap bitmap;
- public int rotationDegrees;
-
- public BitmapWithMetadata(Bitmap bitmap, int rotationDegrees) {
- this.bitmap = bitmap;
- this.rotationDegrees = rotationDegrees;
- }
-}
diff --git a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java b/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java
deleted file mode 100644
index 30868c22b..000000000
--- a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.data;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.util.DisplayMetrics;
-import android.view.WindowManager;
-
-import com.android.camera.Exif;
-import com.android.photos.data.GalleryBitmapPool;
-
-public class MtpBitmapFetch {
- private static int sMaxSize = 0;
-
- public static void recycleThumbnail(Bitmap b) {
- if (b != null) {
- GalleryBitmapPool.getInstance().put(b);
- }
- }
-
- public static Bitmap getThumbnail(MtpDevice device, MtpObjectInfo info) {
- byte[] imageBytes = device.getThumbnail(info.getObjectHandle());
- if (imageBytes == null) {
- return null;
- }
- BitmapFactory.Options o = new BitmapFactory.Options();
- o.inJustDecodeBounds = true;
- BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
- if (o.outWidth == 0 || o.outHeight == 0) {
- return null;
- }
- o.inBitmap = GalleryBitmapPool.getInstance().get(o.outWidth, o.outHeight);
- o.inMutable = true;
- o.inJustDecodeBounds = false;
- o.inSampleSize = 1;
- try {
- return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
- } catch (IllegalArgumentException e) {
- // BitmapFactory throws an exception rather than returning null
- // when image decoding fails and an existing bitmap was supplied
- // for recycling, even if the failure was not caused by the use
- // of that bitmap.
- return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
- }
- }
-
- public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info) {
- return getFullsize(device, info, sMaxSize);
- }
-
- public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info, int maxSide) {
- byte[] imageBytes = device.getObject(info.getObjectHandle(), info.getCompressedSize());
- if (imageBytes == null) {
- return null;
- }
- Bitmap created;
- if (maxSide > 0) {
- BitmapFactory.Options o = new BitmapFactory.Options();
- o.inJustDecodeBounds = true;
- BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
- int w = o.outWidth;
- int h = o.outHeight;
- int comp = Math.max(h, w);
- int sampleSize = 1;
- while ((comp >> 1) >= maxSide) {
- comp = comp >> 1;
- sampleSize++;
- }
- o.inSampleSize = sampleSize;
- o.inJustDecodeBounds = false;
- created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
- } else {
- created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
- }
- if (created == null) {
- return null;
- }
-
- return new BitmapWithMetadata(created, Exif.getOrientation(imageBytes));
- }
-
- public static void configureForContext(Context context) {
- DisplayMetrics metrics = new DisplayMetrics();
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- wm.getDefaultDisplay().getMetrics(metrics);
- sMaxSize = Math.max(metrics.heightPixels, metrics.widthPixels);
- }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/DateTileView.java b/src/com/android/gallery3d/ingest/ui/DateTileView.java
deleted file mode 100644
index 52fe9b85b..000000000
--- a/src/com/android/gallery3d/ingest/ui/DateTileView.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.SimpleDate;
-
-import java.text.DateFormatSymbols;
-import java.util.Locale;
-
-public class DateTileView extends FrameLayout {
- private static String[] sMonthNames = DateFormatSymbols.getInstance().getShortMonths();
- private static Locale sLocale;
-
- static {
- refreshLocale();
- }
-
- public static boolean refreshLocale() {
- Locale currentLocale = Locale.getDefault();
- if (!currentLocale.equals(sLocale)) {
- sLocale = currentLocale;
- sMonthNames = DateFormatSymbols.getInstance(sLocale).getShortMonths();
- return true;
- } else {
- return false;
- }
- }
-
- private TextView mDateTextView;
- private TextView mMonthTextView;
- private TextView mYearTextView;
- private int mMonth = -1;
- private int mYear = -1;
- private int mDate = -1;
- private String[] mMonthNames = sMonthNames;
-
- public DateTileView(Context context) {
- super(context);
- }
-
- public DateTileView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public DateTileView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Force this to be square
- super.onMeasure(widthMeasureSpec, widthMeasureSpec);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mDateTextView = (TextView) findViewById(R.id.date_tile_day);
- mMonthTextView = (TextView) findViewById(R.id.date_tile_month);
- mYearTextView = (TextView) findViewById(R.id.date_tile_year);
- }
-
- public void setDate(SimpleDate date) {
- setDate(date.getDay(), date.getMonth(), date.getYear());
- }
-
- public void setDate(int date, int month, int year) {
- if (date != mDate) {
- mDate = date;
- mDateTextView.setText(mDate > 9 ? Integer.toString(mDate) : "0" + mDate);
- }
- if (mMonthNames != sMonthNames) {
- mMonthNames = sMonthNames;
- if (month == mMonth) {
- mMonthTextView.setText(mMonthNames[mMonth]);
- }
- }
- if (month != mMonth) {
- mMonth = month;
- mMonthTextView.setText(mMonthNames[mMonth]);
- }
- if (year != mYear) {
- mYear = year;
- mYearTextView.setText(Integer.toString(mYear));
- }
- }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/IngestGridView.java b/src/com/android/gallery3d/ingest/ui/IngestGridView.java
deleted file mode 100644
index c821259fe..000000000
--- a/src/com/android/gallery3d/ingest/ui/IngestGridView.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.GridView;
-
-/**
- * This just extends GridView with the ability to listen for calls
- * to clearChoices()
- */
-public class IngestGridView extends GridView {
-
- public interface OnClearChoicesListener {
- public void onClearChoices();
- }
-
- private OnClearChoicesListener mOnClearChoicesListener = null;
-
- public IngestGridView(Context context) {
- super(context);
- }
-
- public IngestGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public IngestGridView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public void setOnClearChoicesListener(OnClearChoicesListener l) {
- mOnClearChoicesListener = l;
- }
-
- @Override
- public void clearChoices() {
- super.clearChoices();
- if (mOnClearChoicesListener != null) {
- mOnClearChoicesListener.onClearChoices();
- }
- }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java b/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
deleted file mode 100644
index 8d3884dc6..000000000
--- a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.CheckBox;
-import android.widget.Checkable;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.RelativeLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.adapter.CheckBroker;
-
-public class MtpFullscreenView extends RelativeLayout implements Checkable,
- CompoundButton.OnCheckedChangeListener, CheckBroker.OnCheckedChangedListener {
-
- private MtpImageView mImageView;
- private CheckBox mCheckbox;
- private int mPosition = -1;
- private CheckBroker mBroker;
-
- public MtpFullscreenView(Context context) {
- super(context);
- }
-
- public MtpFullscreenView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public MtpFullscreenView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mImageView = (MtpImageView) findViewById(R.id.ingest_fullsize_image);
- mCheckbox = (CheckBox) findViewById(R.id.ingest_fullsize_image_checkbox);
- mCheckbox.setOnCheckedChangeListener(this);
- }
-
- @Override
- public boolean isChecked() {
- return mCheckbox.isChecked();
- }
-
- @Override
- public void setChecked(boolean checked) {
- mCheckbox.setChecked(checked);
- }
-
- @Override
- public void toggle() {
- mCheckbox.toggle();
- }
-
- @Override
- public void onDetachedFromWindow() {
- setPositionAndBroker(-1, null);
- super.onDetachedFromWindow();
- }
-
- public MtpImageView getImageView() {
- return mImageView;
- }
-
- public int getPosition() {
- return mPosition;
- }
-
- public void setPositionAndBroker(int position, CheckBroker b) {
- if (mBroker != null) {
- mBroker.unregisterOnCheckedChangeListener(this);
- }
- mPosition = position;
- mBroker = b;
- if (mBroker != null) {
- setChecked(mBroker.isItemChecked(position));
- mBroker.registerOnCheckedChangeListener(this);
- }
- }
-
- @Override
- public void onCheckedChanged(CompoundButton arg0, boolean isChecked) {
- if (mBroker != null) mBroker.setItemChecked(mPosition, isChecked);
- }
-
- @Override
- public void onCheckedChanged(int position, boolean isChecked) {
- if (position == mPosition) {
- setChecked(isChecked);
- }
- }
-
- @Override
- public void onBulkCheckedChanged() {
- if(mBroker != null) setChecked(mBroker.isItemChecked(mPosition));
- }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpImageView.java b/src/com/android/gallery3d/ingest/ui/MtpImageView.java
deleted file mode 100644
index 80c105126..000000000
--- a/src/com/android/gallery3d/ingest/ui/MtpImageView.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.drawable.Drawable;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.MtpDeviceIndex;
-import com.android.gallery3d.ingest.data.BitmapWithMetadata;
-import com.android.gallery3d.ingest.data.MtpBitmapFetch;
-
-import java.lang.ref.WeakReference;
-
-public class MtpImageView extends ImageView {
- // We will use the thumbnail for images larger than this threshold
- private static final int MAX_FULLSIZE_PREVIEW_SIZE = 8388608; // 8 megabytes
-
- private int mObjectHandle;
- private int mGeneration;
-
- private WeakReference<MtpImageView> mWeakReference = new WeakReference<MtpImageView>(this);
- private Object mFetchLock = new Object();
- private boolean mFetchPending = false;
- private MtpObjectInfo mFetchObjectInfo;
- private MtpDevice mFetchDevice;
- private Object mFetchResult;
- private Drawable mOverlayIcon;
- private boolean mShowOverlayIcon;
-
- private static final FetchImageHandler sFetchHandler = FetchImageHandler.createOnNewThread();
- private static final ShowImageHandler sFetchCompleteHandler = new ShowImageHandler();
-
- private void init() {
- showPlaceholder();
- }
-
- public MtpImageView(Context context) {
- super(context);
- init();
- }
-
- public MtpImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public MtpImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- private void showPlaceholder() {
- setImageResource(android.R.color.transparent);
- }
-
- public void setMtpDeviceAndObjectInfo(MtpDevice device, MtpObjectInfo object, int gen) {
- int handle = object.getObjectHandle();
- if (handle == mObjectHandle && gen == mGeneration) {
- return;
- }
- cancelLoadingAndClear();
- showPlaceholder();
- mGeneration = gen;
- mObjectHandle = handle;
- mShowOverlayIcon = MtpDeviceIndex.SUPPORTED_VIDEO_FORMATS.contains(object.getFormat());
- if (mShowOverlayIcon && mOverlayIcon == null) {
- mOverlayIcon = getResources().getDrawable(R.drawable.ic_control_play);
- updateOverlayIconBounds();
- }
- synchronized (mFetchLock) {
- mFetchObjectInfo = object;
- mFetchDevice = device;
- if (mFetchPending) return;
- mFetchPending = true;
- sFetchHandler.sendMessage(
- sFetchHandler.obtainMessage(0, mWeakReference));
- }
- }
-
- protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) {
- if (info.getCompressedSize() <= MAX_FULLSIZE_PREVIEW_SIZE
- && MtpDeviceIndex.SUPPORTED_IMAGE_FORMATS.contains(info.getFormat())) {
- return MtpBitmapFetch.getFullsize(device, info);
- } else {
- return new BitmapWithMetadata(MtpBitmapFetch.getThumbnail(device, info), 0);
- }
- }
-
- private float mLastBitmapWidth;
- private float mLastBitmapHeight;
- private int mLastRotationDegrees;
- private Matrix mDrawMatrix = new Matrix();
-
- private void updateDrawMatrix() {
- mDrawMatrix.reset();
- float dwidth;
- float dheight;
- float vheight = getHeight();
- float vwidth = getWidth();
- float scale;
- boolean rotated90 = (mLastRotationDegrees % 180 != 0);
- if (rotated90) {
- dwidth = mLastBitmapHeight;
- dheight = mLastBitmapWidth;
- } else {
- dwidth = mLastBitmapWidth;
- dheight = mLastBitmapHeight;
- }
- if (dwidth <= vwidth && dheight <= vheight) {
- scale = 1.0f;
- } else {
- scale = Math.min(vwidth / dwidth, vheight / dheight);
- }
- mDrawMatrix.setScale(scale, scale);
- if (rotated90) {
- mDrawMatrix.postTranslate(-dheight * scale * 0.5f,
- -dwidth * scale * 0.5f);
- mDrawMatrix.postRotate(mLastRotationDegrees);
- mDrawMatrix.postTranslate(dwidth * scale * 0.5f,
- dheight * scale * 0.5f);
- }
- mDrawMatrix.postTranslate((vwidth - dwidth * scale) * 0.5f,
- (vheight - dheight * scale) * 0.5f);
- if (!rotated90 && mLastRotationDegrees > 0) {
- // rotated by a multiple of 180
- mDrawMatrix.postRotate(mLastRotationDegrees, vwidth / 2, vheight / 2);
- }
- setImageMatrix(mDrawMatrix);
- }
-
- private static final int OVERLAY_ICON_SIZE_DENOMINATOR = 4;
-
- private void updateOverlayIconBounds() {
- int iheight = mOverlayIcon.getIntrinsicHeight();
- int iwidth = mOverlayIcon.getIntrinsicWidth();
- int vheight = getHeight();
- int vwidth = getWidth();
- float scale_height = ((float) vheight) / (iheight * OVERLAY_ICON_SIZE_DENOMINATOR);
- float scale_width = ((float) vwidth) / (iwidth * OVERLAY_ICON_SIZE_DENOMINATOR);
- if (scale_height >= 1f && scale_width >= 1f) {
- mOverlayIcon.setBounds((vwidth - iwidth) / 2,
- (vheight - iheight) / 2,
- (vwidth + iwidth) / 2,
- (vheight + iheight) / 2);
- } else {
- float scale = Math.min(scale_height, scale_width);
- mOverlayIcon.setBounds((int) (vwidth - scale * iwidth) / 2,
- (int) (vheight - scale * iheight) / 2,
- (int) (vwidth + scale * iwidth) / 2,
- (int) (vheight + scale * iheight) / 2);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (changed && getScaleType() == ScaleType.MATRIX) {
- updateDrawMatrix();
- }
- if (mShowOverlayIcon && changed && mOverlayIcon != null) {
- updateOverlayIconBounds();
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mShowOverlayIcon && mOverlayIcon != null) {
- mOverlayIcon.draw(canvas);
- }
- }
-
- protected void onMtpImageDataFetchedFromDevice(Object result) {
- BitmapWithMetadata bitmapWithMetadata = (BitmapWithMetadata)result;
- if (getScaleType() == ScaleType.MATRIX) {
- mLastBitmapHeight = bitmapWithMetadata.bitmap.getHeight();
- mLastBitmapWidth = bitmapWithMetadata.bitmap.getWidth();
- mLastRotationDegrees = bitmapWithMetadata.rotationDegrees;
- updateDrawMatrix();
- } else {
- setRotation(bitmapWithMetadata.rotationDegrees);
- }
- setAlpha(0f);
- setImageBitmap(bitmapWithMetadata.bitmap);
- animate().alpha(1f);
- }
-
- protected void cancelLoadingAndClear() {
- synchronized (mFetchLock) {
- mFetchDevice = null;
- mFetchObjectInfo = null;
- mFetchResult = null;
- }
- animate().cancel();
- setImageResource(android.R.color.transparent);
- }
-
- @Override
- public void onDetachedFromWindow() {
- cancelLoadingAndClear();
- super.onDetachedFromWindow();
- }
-
- private static class FetchImageHandler extends Handler {
- public FetchImageHandler(Looper l) {
- super(l);
- }
-
- public static FetchImageHandler createOnNewThread() {
- HandlerThread t = new HandlerThread("MtpImageView Fetch");
- t.start();
- return new FetchImageHandler(t.getLooper());
- }
-
- @Override
- public void handleMessage(Message msg) {
- @SuppressWarnings("unchecked")
- MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get();
- if (parent == null) return;
- MtpObjectInfo objectInfo;
- MtpDevice device;
- synchronized (parent.mFetchLock) {
- parent.mFetchPending = false;
- device = parent.mFetchDevice;
- objectInfo = parent.mFetchObjectInfo;
- }
- if (device == null) return;
- Object result = parent.fetchMtpImageDataFromDevice(device, objectInfo);
- if (result == null) return;
- synchronized (parent.mFetchLock) {
- if (parent.mFetchObjectInfo != objectInfo) return;
- parent.mFetchResult = result;
- parent.mFetchDevice = null;
- parent.mFetchObjectInfo = null;
- sFetchCompleteHandler.sendMessage(
- sFetchCompleteHandler.obtainMessage(0, parent.mWeakReference));
- }
- }
- }
-
- private static class ShowImageHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- @SuppressWarnings("unchecked")
- MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get();
- if (parent == null) return;
- Object result;
- synchronized (parent.mFetchLock) {
- result = parent.mFetchResult;
- }
- if (result == null) return;
- parent.onMtpImageDataFetchedFromDevice(result);
- }
- }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java b/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
deleted file mode 100644
index 3307e78aa..000000000
--- a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.gallery3d.ingest.ui;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.mtp.MtpDevice;
-import android.mtp.MtpObjectInfo;
-import android.util.AttributeSet;
-import android.widget.Checkable;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.ingest.data.MtpBitmapFetch;
-
-
-public class MtpThumbnailTileView extends MtpImageView implements Checkable {
-
- private Paint mForegroundPaint;
- private boolean mIsChecked;
- private Bitmap mBitmap;
-
- private void init() {
- mForegroundPaint = new Paint();
- mForegroundPaint.setColor(getResources().getColor(R.color.ingest_highlight_semitransparent));
- }
-
- public MtpThumbnailTileView(Context context) {
- super(context);
- init();
- }
-
- public MtpThumbnailTileView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public MtpThumbnailTileView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- @Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Force this to be square
- super.onMeasure(widthMeasureSpec, widthMeasureSpec);
- }
-
- @Override
- protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) {
- return MtpBitmapFetch.getThumbnail(device, info);
- }
-
- @Override
- protected void onMtpImageDataFetchedFromDevice(Object result) {
- mBitmap = (Bitmap)result;
- setImageBitmap(mBitmap);
- }
-
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
- if (isChecked()) {
- canvas.drawRect(canvas.getClipBounds(), mForegroundPaint);
- }
- }
-
- @Override
- public boolean isChecked() {
- return mIsChecked;
- }
-
- @Override
- public void setChecked(boolean checked) {
- mIsChecked = checked;
- }
-
- @Override
- public void toggle() {
- setChecked(!mIsChecked);
- }
-
- @Override
- protected void cancelLoadingAndClear() {
- super.cancelLoadingAndClear();
- if (mBitmap != null) {
- MtpBitmapFetch.recycleThumbnail(mBitmap);
- mBitmap = null;
- }
- }
-}