package com.android.gallery3d.ingest;
+import com.android.gallery3d.R;
+import com.android.gallery3d.ingest.data.ImportTask;
+import com.android.gallery3d.ingest.data.IngestObjectInfo;
+import com.android.gallery3d.ingest.data.MtpClient;
+import com.android.gallery3d.ingest.data.MtpDeviceIndex;
+
+import android.annotation.TargetApi;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
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.Build;
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.ingest.data.MtpBitmapFetch;
-import com.android.gallery3d.util.BucketNames;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+/**
+ * Service for MTP importing tasks.
+ */
+@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class IngestService extends Service implements ImportTask.Listener,
- MtpDeviceIndex.ProgressListener, MtpClient.Listener {
+ MtpDeviceIndex.ProgressListener, MtpClient.Listener {
- public class LocalBinder extends Binder {
- IngestService getService() {
- return IngestService.this;
- }
+ /**
+ * Convenience class to allow easy access to the service instance.
+ */
+ public class LocalBinder extends Binder {
+ IngestService getService() {
+ return IngestService.this;
}
+ }
- private static final int PROGRESS_UPDATE_INTERVAL_MS = 180;
-
- private static MtpClient sClient;
+ private static final int PROGRESS_UPDATE_INTERVAL_MS = 180;
- 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 Collection<MtpObjectInfo> mRedeliverObjectsNotImported;
- private boolean mRedeliverNotifyIndexChanged = false;
- private boolean mRedeliverIndexFinish = false;
- private NotificationManager mNotificationManager;
- private NotificationCompat.Builder mNotificationBuilder;
- private long mLastProgressIndexTime = 0;
+ private MtpClient mClient;
+ 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<IngestObjectInfo> 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);
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mScannerClient = new ScannerClient(this);
+ mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ mNotificationBuilder = new NotificationCompat.Builder(this);
+ // TODO(georgescu): Use a better drawable for the notificaton?
+ mNotificationBuilder.setSmallIcon(android.R.drawable.stat_notify_sync)
+ .setContentIntent(PendingIntent.getActivity(this, 0,
+ new Intent(this, IngestActivity.class), 0));
+ mIndex = MtpDeviceIndex.getInstance();
+ mIndex.setProgressListener(this);
- if (sClient == null) {
- sClient = new MtpClient(getApplicationContext());
- }
- List<MtpDevice> devices = sClient.getDeviceList();
- if (devices.size() > 0) {
- setDevice(devices.get(0));
- }
- sClient.addListener(this);
+ mClient = new MtpClient(getApplicationContext());
+ List<MtpDevice> devices = mClient.getDeviceList();
+ if (!devices.isEmpty()) {
+ setDevice(devices.get(0));
}
+ mClient.addListener(this);
+ }
- @Override
- public void onDestroy() {
- sClient.removeListener(this);
- mIndex.unsetProgressListener(this);
- super.onDestroy();
- }
+ @Override
+ public void onDestroy() {
+ mClient.close();
+ mIndex.unsetProgressListener(this);
+ super.onDestroy();
+ }
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
+ @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;
- }
+ private void setDevice(MtpDevice device) {
+ if (mDevice == device) {
+ return;
}
-
- protected MtpDeviceIndex getIndex() {
- return mIndex;
+ 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 void setClientActivity(IngestActivity activity) {
- if (mClientActivity == activity) return;
- mClientActivity = activity;
- if (mClientActivity == null) return;
- mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_IMPORTING);
- mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING);
- if (mRedeliverImportFinish) {
- mClientActivity.onImportFinish(mRedeliverObjectsNotImported);
- mRedeliverImportFinish = false;
- mRedeliverObjectsNotImported = null;
- }
- if (mRedeliverNotifyIndexChanged) {
- mClientActivity.notifyIndexChanged();
- mRedeliverNotifyIndexChanged = false;
- }
- if (mRedeliverIndexFinish) {
- mClientActivity.onIndexFinish();
- mRedeliverIndexFinish = false;
- }
+ 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(R.id.ingest_notification_scanning,
+ mNotificationBuilder.build());
+ }
+ return;
+ }
+ mNotificationManager.cancel(R.id.ingest_notification_importing);
+ mNotificationManager.cancel(R.id.ingest_notification_scanning);
+ if (mRedeliverImportFinish) {
+ mClientActivity.onImportFinish(mRedeliverObjectsNotImported,
+ mRedeliverImportFinishCount);
+ mRedeliverImportFinish = false;
+ mRedeliverObjectsNotImported = null;
+ }
+ if (mRedeliverNotifyIndexChanged) {
+ mClientActivity.notifyIndexChanged();
+ mRedeliverNotifyIndexChanged = false;
+ }
+ if (mRedeliverIndexFinish) {
+ mClientActivity.onIndexingFinished();
+ mRedeliverIndexFinish = false;
}
+ if (mDevice != null) {
+ mNeedRelaunchNotification = true;
+ }
+ }
- protected void importSelectedItems(SparseBooleanArray selected, Adapter adapter) {
- List<MtpObjectInfo> importHandles = new ArrayList<MtpObjectInfo>();
- for (int i = 0; i < selected.size(); i++) {
- if (selected.valueAt(i)) {
- Object item = adapter.getItem(selected.keyAt(i));
- if (item instanceof MtpObjectInfo) {
- importHandles.add(((MtpObjectInfo) item));
- }
- }
+ protected void importSelectedItems(SparseBooleanArray selected, Adapter adapter) {
+ List<IngestObjectInfo> importHandles = new ArrayList<IngestObjectInfo>();
+ for (int i = 0; i < selected.size(); i++) {
+ if (selected.valueAt(i)) {
+ Object item = adapter.getItem(selected.keyAt(i));
+ if (item instanceof IngestObjectInfo) {
+ importHandles.add(((IngestObjectInfo) 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();
+ }
}
+ ImportTask task = new ImportTask(mDevice, importHandles, mDevicePrettyName, this);
+ task.setListener(this);
+ mNotificationBuilder.setProgress(0, 0, true)
+ .setContentText(getResources().getText(R.string.ingest_importing));
+ startForeground(R.id.ingest_notification_importing,
+ mNotificationBuilder.build());
+ new Thread(task).start();
+ }
- @Override
- public void deviceAdded(MtpDevice device) {
- if (mDevice == null) {
- setDevice(device);
- }
+ @Override
+ public void deviceAdded(MtpDevice device) {
+ if (mDevice == null) {
+ setDevice(device);
}
+ }
+
+ @Override
+ public void deviceRemoved(MtpDevice device) {
+ if (device == mDevice) {
+ mNotificationManager.cancel(R.id.ingest_notification_scanning);
+ mNotificationManager.cancel(R.id.ingest_notification_importing);
+ setDevice(null);
+ mNeedRelaunchNotification = false;
- @Override
- public void deviceRemoved(MtpDevice device) {
- if (device == mDevice) {
- setDevice(null);
- MtpBitmapFetch.onDeviceDisconnected(device);
- }
}
+ }
- @Override
- public void onImportProgress(int visitedCount, int totalCount,
- String pathIfSuccessful) {
- if (pathIfSuccessful != null) {
- mScannerClient.scanPath(pathIfSuccessful);
- }
- 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 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(R.id.ingest_notification_importing,
+ mNotificationBuilder.build());
+ }
- @Override
- public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported) {
- stopForeground(true);
- if (mClientActivity != null) {
- mClientActivity.onImportFinish(objectsNotImported);
- } else {
- mRedeliverImportFinish = true;
- mRedeliverObjectsNotImported = objectsNotImported;
- mNotificationBuilder.setProgress(0, 0, false)
- .setContentText(getResources().getText(R.string.import_complete));
- mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
- mNotificationBuilder.build());
- }
+ @Override
+ public void onImportFinish(Collection<IngestObjectInfo> 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.ingest_import_complete));
+ mNotificationManager.notify(R.id.ingest_notification_importing,
+ mNotificationBuilder.build());
}
+ }
- @Override
- public void onObjectIndexed(MtpObjectInfo object, int numVisited) {
- 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 onObjectIndexed(IngestObjectInfo 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(R.id.ingest_notification_scanning,
+ mNotificationBuilder.build());
+ }
}
+ }
- @Override
- public void onSorting() {
- if (mClientActivity != null) mClientActivity.onSorting();
+ @Override
+ public void onSortingStarted() {
+ if (mClientActivity != null) {
+ mClientActivity.onSortingStarted();
}
+ }
- @Override
- public void onIndexFinish() {
- 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;
- }
+ @Override
+ public void onIndexingFinished() {
+ mNeedRelaunchNotification = true;
+ if (mClientActivity != null) {
+ mClientActivity.onIndexingFinished();
+ } else {
+ mNotificationBuilder.setProgress(0, 0, false)
+ .setContentText(getResources().getText(R.string.ingest_scanning_done));
+ mNotificationManager.notify(R.id.ingest_notification_scanning,
+ mNotificationBuilder.build());
+ mRedeliverIndexFinish = true;
}
+ }
- // Copied from old Gallery3d code
- private static final class ScannerClient implements MediaScannerConnectionClient {
- ArrayList<String> mPaths = new ArrayList<String>();
- MediaScannerConnection mScannerConnection;
- boolean mConnected;
- Object mLock = new Object();
+ // Copied from old Gallery3d code
+ private static final class ScannerClient implements MediaScannerConnectionClient {
+ ArrayList<String> mPaths = new ArrayList<String>();
+ MediaScannerConnection mScannerConnection;
+ boolean mConnected;
+ Object mLock = new Object();
- public ScannerClient(Context context) {
- mScannerConnection = new MediaScannerConnection(context, this);
- }
+ public 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();
- }
- }
+ 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 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) {
- }
+ @Override
+ public void onScanCompleted(String path, Uri uri) {
}
+ }
}