[automerger] DO NOT MERGE Rework thumbnail cleanup am: b514ce9b38 am: b8dad6c644
Change-Id: I8539a02510ed9a61b683c66c66de7d1b319c2603
This commit is contained in:
@@ -672,8 +672,8 @@ public final class MediaStore {
|
||||
// Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo);
|
||||
// If the magic is non-zero, we simply return thumbnail if it does exist.
|
||||
// querying MediaProvider and simply return thumbnail.
|
||||
MiniThumbFile thumbFile = new MiniThumbFile(isVideo ? Video.Media.EXTERNAL_CONTENT_URI
|
||||
: Images.Media.EXTERNAL_CONTENT_URI);
|
||||
MiniThumbFile thumbFile = MiniThumbFile.instance(
|
||||
isVideo ? Video.Media.EXTERNAL_CONTENT_URI : Images.Media.EXTERNAL_CONTENT_URI);
|
||||
Cursor c = null;
|
||||
try {
|
||||
long magic = thumbFile.getMagic(origId);
|
||||
|
||||
@@ -308,7 +308,6 @@ public class MediaScanner
|
||||
private Uri mAudioUri;
|
||||
private Uri mVideoUri;
|
||||
private Uri mImagesUri;
|
||||
private Uri mThumbsUri;
|
||||
private Uri mPlaylistsUri;
|
||||
private Uri mFilesUri;
|
||||
private Uri mFilesUriNoNotify;
|
||||
@@ -1164,64 +1163,6 @@ public class MediaScanner
|
||||
}
|
||||
}
|
||||
|
||||
private boolean inScanDirectory(String path, String[] directories) {
|
||||
for (int i = 0; i < directories.length; i++) {
|
||||
String directory = directories[i];
|
||||
if (path.startsWith(directory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void pruneDeadThumbnailFiles() {
|
||||
HashSet<String> existingFiles = new HashSet<String>();
|
||||
String directory = "/sdcard/DCIM/.thumbnails";
|
||||
String [] files = (new File(directory)).list();
|
||||
Cursor c = null;
|
||||
if (files == null)
|
||||
files = new String[0];
|
||||
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
String fullPathString = directory + "/" + files[i];
|
||||
existingFiles.add(fullPathString);
|
||||
}
|
||||
|
||||
try {
|
||||
c = mMediaProvider.query(
|
||||
mPackageName,
|
||||
mThumbsUri,
|
||||
new String [] { "_data" },
|
||||
null,
|
||||
null,
|
||||
null, null);
|
||||
Log.v(TAG, "pruneDeadThumbnailFiles... " + c);
|
||||
if (c != null && c.moveToFirst()) {
|
||||
do {
|
||||
String fullPathString = c.getString(0);
|
||||
existingFiles.remove(fullPathString);
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
|
||||
for (String fileToDelete : existingFiles) {
|
||||
if (false)
|
||||
Log.v(TAG, "fileToDelete is " + fileToDelete);
|
||||
try {
|
||||
(new File(fileToDelete)).delete();
|
||||
} catch (SecurityException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
Log.v(TAG, "/pruneDeadThumbnailFiles... " + c);
|
||||
} catch (RemoteException e) {
|
||||
// We will soon be killed...
|
||||
} finally {
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MediaBulkDeleter {
|
||||
StringBuilder whereClause = new StringBuilder();
|
||||
ArrayList<String> whereArgs = new ArrayList<String>(100);
|
||||
@@ -1267,9 +1208,6 @@ public class MediaScanner
|
||||
processPlayLists();
|
||||
}
|
||||
|
||||
if (mOriginalCount == 0 && mImagesUri.equals(Images.Media.getContentUri("external")))
|
||||
pruneDeadThumbnailFiles();
|
||||
|
||||
// allow GC to clean up
|
||||
mPlayLists = null;
|
||||
mMediaProvider = null;
|
||||
@@ -1289,7 +1227,6 @@ public class MediaScanner
|
||||
mAudioUri = Audio.Media.getContentUri(volumeName);
|
||||
mVideoUri = Video.Media.getContentUri(volumeName);
|
||||
mImagesUri = Images.Media.getContentUri(volumeName);
|
||||
mThumbsUri = Images.Thumbnails.getContentUri(volumeName);
|
||||
mFilesUri = Files.getContentUri(volumeName);
|
||||
mFilesUriNoNotify = mFilesUri.buildUpon().appendQueryParameter("nonotify", "1").build();
|
||||
|
||||
|
||||
@@ -44,13 +44,14 @@ import java.util.Hashtable;
|
||||
*/
|
||||
public class MiniThumbFile {
|
||||
private static final String TAG = "MiniThumbFile";
|
||||
private static final int MINI_THUMB_DATA_FILE_VERSION = 3;
|
||||
private static final int MINI_THUMB_DATA_FILE_VERSION = 4;
|
||||
public static final int BYTES_PER_MINTHUMB = 10000;
|
||||
private static final int HEADER_SIZE = 1 + 8 + 4;
|
||||
private Uri mUri;
|
||||
private RandomAccessFile mMiniThumbFile;
|
||||
private FileChannel mChannel;
|
||||
private ByteBuffer mBuffer;
|
||||
private ByteBuffer mEmptyBuffer;
|
||||
private static final Hashtable<String, MiniThumbFile> sThumbFiles =
|
||||
new Hashtable<String, MiniThumbFile>();
|
||||
|
||||
@@ -127,9 +128,10 @@ public class MiniThumbFile {
|
||||
return mMiniThumbFile;
|
||||
}
|
||||
|
||||
public MiniThumbFile(Uri uri) {
|
||||
private MiniThumbFile(Uri uri) {
|
||||
mUri = uri;
|
||||
mBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
|
||||
mEmptyBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
|
||||
}
|
||||
|
||||
public synchronized void deactivate() {
|
||||
@@ -184,6 +186,54 @@ public class MiniThumbFile {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public synchronized void eraseMiniThumb(long id) {
|
||||
RandomAccessFile r = miniThumbDataFile();
|
||||
if (r != null) {
|
||||
long pos = id * BYTES_PER_MINTHUMB;
|
||||
FileLock lock = null;
|
||||
try {
|
||||
mBuffer.clear();
|
||||
mBuffer.limit(1 + 8);
|
||||
|
||||
lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false);
|
||||
// check that we can read the following 9 bytes
|
||||
// (1 for the "status" and 8 for the long)
|
||||
if (mChannel.read(mBuffer, pos) == 9) {
|
||||
mBuffer.position(0);
|
||||
if (mBuffer.get() == 1) {
|
||||
long currentMagic = mBuffer.getLong();
|
||||
if (currentMagic == 0) {
|
||||
// there is no thumbnail stored here
|
||||
Log.i(TAG, "no thumbnail for id " + id);
|
||||
return;
|
||||
}
|
||||
// zero out the thumbnail slot
|
||||
// Log.v(TAG, "clearing slot " + id + ", magic " + currentMagic
|
||||
// + " at offset " + pos);
|
||||
mChannel.write(mEmptyBuffer, pos);
|
||||
}
|
||||
} else {
|
||||
// Log.v(TAG, "No slot");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Log.v(TAG, "Got exception checking file magic: ", ex);
|
||||
} catch (RuntimeException ex) {
|
||||
// Other NIO related exception like disk full, read only channel..etc
|
||||
Log.e(TAG, "Got exception when reading magic, id = " + id +
|
||||
", disk full or mount read-only? " + ex.getClass());
|
||||
} finally {
|
||||
try {
|
||||
if (lock != null) lock.release();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore it.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Log.v(TAG, "No data file");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void saveMiniThumbToFile(byte[] data, long id, long magic)
|
||||
throws IOException {
|
||||
RandomAccessFile r = miniThumbDataFile();
|
||||
|
||||
Reference in New Issue
Block a user