diff options
Diffstat (limited to 'src/com/android/photos/data/MediaCacheDatabase.java')
-rw-r--r-- | src/com/android/photos/data/MediaCacheDatabase.java | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/src/com/android/photos/data/MediaCacheDatabase.java b/src/com/android/photos/data/MediaCacheDatabase.java new file mode 100644 index 000000000..16265b574 --- /dev/null +++ b/src/com/android/photos/data/MediaCacheDatabase.java @@ -0,0 +1,272 @@ +/* + * 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.photos.data; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.net.Uri; +import android.provider.BaseColumns; + +import com.android.photos.data.MediaRetriever.MediaSize; + +import java.io.File; + +class MediaCacheDatabase extends SQLiteOpenHelper { + public static final int DB_VERSION = 1; + public static final String DB_NAME = "mediacache.db"; + + /** Internal database table used for the media cache */ + public static final String TABLE = "media_cache"; + + private static interface Columns extends BaseColumns { + /** The Content URI of the original image. */ + public static final String URI = "uri"; + /** MediaSize.getValue() values. */ + public static final String MEDIA_SIZE = "media_size"; + /** The last time this image was queried. */ + public static final String LAST_ACCESS = "last_access"; + /** The image size in bytes. */ + public static final String SIZE_IN_BYTES = "size"; + } + + static interface Action { + void execute(Uri uri, long id, MediaRetriever.MediaSize size, Object parameter); + } + + private static final String[] PROJECTION_ID = { + Columns._ID, + }; + + private static final String[] PROJECTION_CACHED = { + Columns._ID, Columns.MEDIA_SIZE, Columns.SIZE_IN_BYTES, + }; + + private static final String[] PROJECTION_CACHE_SIZE = { + "SUM(" + Columns.SIZE_IN_BYTES + ")" + }; + + private static final String[] PROJECTION_DELETE_OLD = { + Columns._ID, Columns.URI, Columns.MEDIA_SIZE, Columns.SIZE_IN_BYTES, Columns.LAST_ACCESS, + }; + + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE + "(" + + Columns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + Columns.URI + " TEXT NOT NULL," + + Columns.MEDIA_SIZE + " INTEGER NOT NULL," + + Columns.LAST_ACCESS + " INTEGER NOT NULL," + + Columns.SIZE_IN_BYTES + " INTEGER NOT NULL," + + "UNIQUE(" + Columns.URI + ", " + Columns.MEDIA_SIZE + "))"; + + public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE; + + public static final String WHERE_THUMBNAIL = Columns.MEDIA_SIZE + " = " + + MediaSize.Thumbnail.getValue(); + + public static final String WHERE_NOT_THUMBNAIL = Columns.MEDIA_SIZE + " <> " + + MediaSize.Thumbnail.getValue(); + + public static final String WHERE_CLEAR_CACHE = Columns.LAST_ACCESS + " <= ?"; + + public static final String WHERE_CLEAR_CACHE_LARGE = WHERE_CLEAR_CACHE + " AND " + + WHERE_NOT_THUMBNAIL; + + static class QueryCacheResults { + public QueryCacheResults(long id, int sizeVal) { + this.id = id; + this.size = MediaRetriever.MediaSize.fromInteger(sizeVal); + } + public long id; + public MediaRetriever.MediaSize size; + } + + public MediaCacheDatabase(Context context) { + super(context, DB_NAME, null, DB_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(CREATE_TABLE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL(DROP_TABLE); + onCreate(db); + MediaCache.getInstance().clearCacheDir(); + } + + public Long getCached(Uri uri, MediaRetriever.MediaSize size) { + String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " = ?"; + SQLiteDatabase db = getWritableDatabase(); + String[] whereArgs = { + uri.toString(), String.valueOf(size.getValue()), + }; + Cursor cursor = db.query(TABLE, PROJECTION_ID, where, whereArgs, null, null, null); + Long id = null; + if (cursor.moveToNext()) { + id = cursor.getLong(0); + } + cursor.close(); + if (id != null) { + String[] updateArgs = { + id.toString() + }; + ContentValues values = new ContentValues(); + values.put(Columns.LAST_ACCESS, System.currentTimeMillis()); + db.beginTransaction(); + try { + db.update(TABLE, values, Columns._ID + " = ?", updateArgs); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + return id; + } + + public MediaRetriever.MediaSize executeOnBestCached(Uri uri, MediaRetriever.MediaSize size, Action action) { + String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " < ?"; + String orderBy = Columns.MEDIA_SIZE + " DESC"; + SQLiteDatabase db = getReadableDatabase(); + String[] whereArgs = { + uri.toString(), String.valueOf(size.getValue()), + }; + Cursor cursor = db.query(TABLE, PROJECTION_CACHED, where, whereArgs, null, null, orderBy); + MediaRetriever.MediaSize bestSize = null; + if (cursor.moveToNext()) { + long id = cursor.getLong(0); + bestSize = MediaRetriever.MediaSize.fromInteger(cursor.getInt(1)); + long fileSize = cursor.getLong(2); + action.execute(uri, id, bestSize, fileSize); + } + cursor.close(); + return bestSize; + } + + public long insert(Uri uri, MediaRetriever.MediaSize size, Action action, File tempFile) { + SQLiteDatabase db = getWritableDatabase(); + db.beginTransaction(); + try { + ContentValues values = new ContentValues(); + values.put(Columns.LAST_ACCESS, System.currentTimeMillis()); + values.put(Columns.MEDIA_SIZE, size.getValue()); + values.put(Columns.URI, uri.toString()); + values.put(Columns.SIZE_IN_BYTES, tempFile.length()); + long id = db.insert(TABLE, null, values); + if (id != -1) { + action.execute(uri, id, size, tempFile); + db.setTransactionSuccessful(); + } + return id; + } finally { + db.endTransaction(); + } + } + + public void updateLength(long id, long fileSize) { + ContentValues values = new ContentValues(); + values.put(Columns.SIZE_IN_BYTES, fileSize); + String[] whereArgs = { + String.valueOf(id) + }; + SQLiteDatabase db = getWritableDatabase(); + db.beginTransaction(); + try { + db.update(TABLE, values, Columns._ID + " = ?", whereArgs); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + public void delete(Uri uri, Action action) { + SQLiteDatabase db = getWritableDatabase(); + String where = Columns.URI + " = ?"; + String[] whereArgs = { + uri.toString() + }; + Cursor cursor = db.query(TABLE, PROJECTION_CACHED, where, whereArgs, null, null, null); + while (cursor.moveToNext()) { + long id = cursor.getLong(0); + MediaRetriever.MediaSize size = MediaRetriever.MediaSize.fromInteger(cursor.getInt(1)); + action.execute(uri, id, size, null); + } + cursor.close(); + db.beginTransaction(); + try { + db.delete(TABLE, where, whereArgs); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + public void deleteOldCached(boolean includeThumbnails, long deleteSize, Action action) { + String where = includeThumbnails ? null : WHERE_NOT_THUMBNAIL; + long lastAccess = 0; + SQLiteDatabase db = getWritableDatabase(); + db.beginTransaction(); + try { + Cursor cursor = db.query(TABLE, PROJECTION_DELETE_OLD, where, null, null, null, + Columns.LAST_ACCESS); + while (cursor.moveToNext()) { + long id = cursor.getLong(0); + String uri = cursor.getString(1); + MediaSize size = MediaSize.fromInteger(cursor.getInt(2)); + long length = cursor.getLong(3); + long imageLastAccess = cursor.getLong(4); + + if (imageLastAccess != lastAccess && deleteSize < 0) { + break; // We've deleted enough. + } + lastAccess = imageLastAccess; + action.execute(Uri.parse(uri), id, size, length); + deleteSize -= length; + } + cursor.close(); + String[] whereArgs = { + String.valueOf(lastAccess), + }; + String whereDelete = includeThumbnails ? WHERE_CLEAR_CACHE : WHERE_CLEAR_CACHE_LARGE; + db.delete(TABLE, whereDelete, whereArgs); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + public long getCacheSize() { + return getCacheSize(null); + } + + public long getThumbnailCacheSize() { + return getCacheSize(WHERE_THUMBNAIL); + } + + private long getCacheSize(String where) { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.query(TABLE, PROJECTION_CACHE_SIZE, where, null, null, null, null); + long size = -1; + if (cursor.moveToNext()) { + size = cursor.getLong(0); + } + cursor.close(); + return size; + } +} |