From 8e963a5a6016d246184ed65906f9d103e92b17e2 Mon Sep 17 00:00:00 2001 From: Sascha Haeberling Date: Tue, 6 Aug 2013 11:43:02 -0700 Subject: This removes all non-Camera stuff from Camera2. Note: Camera2 is a clone of Gallery2 right now. Note 2: I will bring .mk files back later. Change-Id: Ida958654296f5ebaacb6bb0ff59d52a7c37ce6fc --- src/com/android/gallery3d/ingest/ImportTask.java | 95 ---- .../android/gallery3d/ingest/IngestActivity.java | 570 -------------------- .../android/gallery3d/ingest/IngestService.java | 320 ----------- .../android/gallery3d/ingest/MtpDeviceIndex.java | 596 --------------------- src/com/android/gallery3d/ingest/SimpleDate.java | 114 ---- .../gallery3d/ingest/adapter/CheckBroker.java | 56 -- .../gallery3d/ingest/adapter/MtpAdapter.java | 192 ------- .../gallery3d/ingest/adapter/MtpPagerAdapter.java | 102 ---- .../gallery3d/ingest/data/BitmapWithMetadata.java | 29 - .../gallery3d/ingest/data/MtpBitmapFetch.java | 106 ---- .../android/gallery3d/ingest/ui/DateTileView.java | 107 ---- .../gallery3d/ingest/ui/IngestGridView.java | 58 -- .../gallery3d/ingest/ui/MtpFullscreenView.java | 115 ---- .../android/gallery3d/ingest/ui/MtpImageView.java | 280 ---------- .../gallery3d/ingest/ui/MtpThumbnailTileView.java | 106 ---- 15 files changed, 2846 deletions(-) delete mode 100644 src/com/android/gallery3d/ingest/ImportTask.java delete mode 100644 src/com/android/gallery3d/ingest/IngestActivity.java delete mode 100644 src/com/android/gallery3d/ingest/IngestService.java delete mode 100644 src/com/android/gallery3d/ingest/MtpDeviceIndex.java delete mode 100644 src/com/android/gallery3d/ingest/SimpleDate.java delete mode 100644 src/com/android/gallery3d/ingest/adapter/CheckBroker.java delete mode 100644 src/com/android/gallery3d/ingest/adapter/MtpAdapter.java delete mode 100644 src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java delete mode 100644 src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java delete mode 100644 src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java delete mode 100644 src/com/android/gallery3d/ingest/ui/DateTileView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/IngestGridView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/MtpImageView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java (limited to 'src/com/android/gallery3d/ingest') 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 objectsNotImported, int visitedCount); - } - - static private final String WAKELOCK_LABEL = "MTP Import Task"; - - private Listener mListener; - private String mDestAlbumName; - private Collection mObjectsToImport; - private MtpDevice mDevice; - private PowerManager.WakeLock mWakeLock; - - public ImportTask(MtpDevice device, Collection 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 objectsNotImported = new LinkedList(); - 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 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 mParentReference; - - public ItemListHandler(IngestActivity parent) { - super(); - mParentReference = new WeakReference(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 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 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 importHandles = new ArrayList(); - 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 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 mPaths = new ArrayList(); - 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 SUPPORTED_IMAGE_FORMATS; - public static final Set SUPPORTED_VIDEO_FORMATS; - - static { - SUPPORTED_IMAGE_FORMATS = new HashSet(); - 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(); - 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 { - SimpleDate bucket; - List tempElementsList = new ArrayList(); - 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 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 { - @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 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(); - for (int storageId : mDevice.getStorageIds()) { - if (mDevice != getDevice()) throw new IndexingException(); - Stack pendingDirectories = new Stack(); - 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 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 { - 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 mListeners = - new ArrayList(); - - 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 mWeakReference = new WeakReference(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) 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) 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; - } - } -} -- cgit v1.2.3