summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/data/SecureAlbum.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/data/SecureAlbum.java')
-rw-r--r--src/com/android/gallery3d/data/SecureAlbum.java206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/data/SecureAlbum.java b/src/com/android/gallery3d/data/SecureAlbum.java
new file mode 100644
index 000000000..204f848f8
--- /dev/null
+++ b/src/com/android/gallery3d/data/SecureAlbum.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2012 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.data;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.MediaColumns;
+import android.provider.MediaStore.Video;
+
+import com.android.gallery3d.app.GalleryApp;
+import com.android.gallery3d.app.StitchingChangeListener;
+import com.android.gallery3d.util.MediaSetUtils;
+
+import java.util.ArrayList;
+
+// This class lists all media items added by the client.
+public class SecureAlbum extends MediaSet implements StitchingChangeListener {
+ @SuppressWarnings("unused")
+ private static final String TAG = "SecureAlbum";
+ private static final String[] PROJECTION = {MediaColumns._ID};
+ private int mMinImageId = Integer.MAX_VALUE; // the smallest id of images
+ private int mMaxImageId = Integer.MIN_VALUE; // the biggest id in images
+ private int mMinVideoId = Integer.MAX_VALUE; // the smallest id of videos
+ private int mMaxVideoId = Integer.MIN_VALUE; // the biggest id of videos
+ // All the media items added by the client.
+ private ArrayList<Path> mAllItems = new ArrayList<Path>();
+ // The types of items in mAllItems. True is video and false is image.
+ private ArrayList<Boolean> mAllItemTypes = new ArrayList<Boolean>();
+ private ArrayList<Path> mExistingItems = new ArrayList<Path>();
+ private Context mContext;
+ private DataManager mDataManager;
+ private static final Uri[] mWatchUris =
+ {Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI};
+ private final ChangeNotifier mNotifier;
+ // A placeholder image in the end of secure album. When it is tapped, it
+ // will take the user to the lock screen.
+ private MediaItem mUnlockItem;
+ private boolean mShowUnlockItem;
+
+ public SecureAlbum(Path path, GalleryApp application, MediaItem unlock) {
+ super(path, nextVersionNumber());
+ mContext = application.getAndroidContext();
+ mDataManager = application.getDataManager();
+ mNotifier = new ChangeNotifier(this, mWatchUris, application);
+ mUnlockItem = unlock;
+ mShowUnlockItem = (!isCameraBucketEmpty(Images.Media.EXTERNAL_CONTENT_URI)
+ || !isCameraBucketEmpty(Video.Media.EXTERNAL_CONTENT_URI));
+ }
+
+ public void addMediaItem(boolean isVideo, int id) {
+ Path pathBase;
+ if (isVideo) {
+ pathBase = LocalVideo.ITEM_PATH;
+ mMinVideoId = Math.min(mMinVideoId, id);
+ mMaxVideoId = Math.max(mMaxVideoId, id);
+ } else {
+ pathBase = LocalImage.ITEM_PATH;
+ mMinImageId = Math.min(mMinImageId, id);
+ mMaxImageId = Math.max(mMaxImageId, id);
+ }
+ Path path = pathBase.getChild(id);
+ if (!mAllItems.contains(path)) {
+ mAllItems.add(path);
+ mAllItemTypes.add(isVideo);
+ mNotifier.fakeChange();
+ }
+ }
+
+ // The sequence is stitching items, local media items, and unlock image.
+ @Override
+ public ArrayList<MediaItem> getMediaItem(int start, int count) {
+ int existingCount = mExistingItems.size();
+ if (start >= existingCount + 1) {
+ return new ArrayList<MediaItem>();
+ }
+
+ // Add paths of requested stitching items.
+ int end = Math.min(start + count, existingCount);
+ ArrayList<Path> subset = new ArrayList<Path>(mExistingItems.subList(start, end));
+
+ // Convert paths to media items.
+ final MediaItem[] buf = new MediaItem[end - start];
+ ItemConsumer consumer = new ItemConsumer() {
+ @Override
+ public void consume(int index, MediaItem item) {
+ buf[index] = item;
+ }
+ };
+ mDataManager.mapMediaItems(subset, consumer, 0);
+ ArrayList<MediaItem> result = new ArrayList<MediaItem>(end - start);
+ for (int i = 0; i < buf.length; i++) {
+ result.add(buf[i]);
+ }
+ if (mShowUnlockItem) result.add(mUnlockItem);
+ return result;
+ }
+
+ @Override
+ public int getMediaItemCount() {
+ return (mExistingItems.size() + (mShowUnlockItem ? 1 : 0));
+ }
+
+ @Override
+ public String getName() {
+ return "secure";
+ }
+
+ @Override
+ public long reload() {
+ if (mNotifier.isDirty()) {
+ mDataVersion = nextVersionNumber();
+ updateExistingItems();
+ }
+ return mDataVersion;
+ }
+
+ private ArrayList<Integer> queryExistingIds(Uri uri, int minId, int maxId) {
+ ArrayList<Integer> ids = new ArrayList<Integer>();
+ if (minId == Integer.MAX_VALUE || maxId == Integer.MIN_VALUE) return ids;
+
+ String[] selectionArgs = {String.valueOf(minId), String.valueOf(maxId)};
+ Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION,
+ "_id BETWEEN ? AND ?", selectionArgs, null);
+ if (cursor == null) return ids;
+ try {
+ while (cursor.moveToNext()) {
+ ids.add(cursor.getInt(0));
+ }
+ } finally {
+ cursor.close();
+ }
+ return ids;
+ }
+
+ private boolean isCameraBucketEmpty(Uri baseUri) {
+ Uri uri = baseUri.buildUpon()
+ .appendQueryParameter("limit", "1").build();
+ String[] selection = {String.valueOf(MediaSetUtils.CAMERA_BUCKET_ID)};
+ Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION,
+ "bucket_id = ?", selection, null);
+ if (cursor == null) return true;
+ try {
+ return (cursor.getCount() == 0);
+ } finally {
+ cursor.close();
+ }
+ }
+
+ private void updateExistingItems() {
+ if (mAllItems.size() == 0) return;
+
+ // Query existing ids.
+ ArrayList<Integer> imageIds = queryExistingIds(
+ Images.Media.EXTERNAL_CONTENT_URI, mMinImageId, mMaxImageId);
+ ArrayList<Integer> videoIds = queryExistingIds(
+ Video.Media.EXTERNAL_CONTENT_URI, mMinVideoId, mMaxVideoId);
+
+ // Construct the existing items list.
+ mExistingItems.clear();
+ for (int i = mAllItems.size() - 1; i >= 0; i--) {
+ Path path = mAllItems.get(i);
+ boolean isVideo = mAllItemTypes.get(i);
+ int id = Integer.parseInt(path.getSuffix());
+ if (isVideo) {
+ if (videoIds.contains(id)) mExistingItems.add(path);
+ } else {
+ if (imageIds.contains(id)) mExistingItems.add(path);
+ }
+ }
+ }
+
+ @Override
+ public boolean isLeafAlbum() {
+ return true;
+ }
+
+ @Override
+ public void onStitchingQueued(Uri uri) {
+ int id = Integer.parseInt(uri.getLastPathSegment());
+ addMediaItem(false, id);
+ }
+
+ @Override
+ public void onStitchingResult(Uri uri) {
+ }
+
+ @Override
+ public void onStitchingProgress(Uri uri, final int progress) {
+ }
+}