[automerger] DO NOT MERGE Rework thumbnail cleanup am: b514ce9b38
Change-Id: I5cb1316547ced23a1259e068d1ea34631d105608
This commit is contained in:
@@ -672,8 +672,8 @@ public final class MediaStore {
|
|||||||
// Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo);
|
// Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo);
|
||||||
// If the magic is non-zero, we simply return thumbnail if it does exist.
|
// If the magic is non-zero, we simply return thumbnail if it does exist.
|
||||||
// querying MediaProvider and simply return thumbnail.
|
// querying MediaProvider and simply return thumbnail.
|
||||||
MiniThumbFile thumbFile = new MiniThumbFile(isVideo ? Video.Media.EXTERNAL_CONTENT_URI
|
MiniThumbFile thumbFile = MiniThumbFile.instance(
|
||||||
: Images.Media.EXTERNAL_CONTENT_URI);
|
isVideo ? Video.Media.EXTERNAL_CONTENT_URI : Images.Media.EXTERNAL_CONTENT_URI);
|
||||||
Cursor c = null;
|
Cursor c = null;
|
||||||
try {
|
try {
|
||||||
long magic = thumbFile.getMagic(origId);
|
long magic = thumbFile.getMagic(origId);
|
||||||
|
|||||||
@@ -308,7 +308,6 @@ public class MediaScanner
|
|||||||
private Uri mAudioUri;
|
private Uri mAudioUri;
|
||||||
private Uri mVideoUri;
|
private Uri mVideoUri;
|
||||||
private Uri mImagesUri;
|
private Uri mImagesUri;
|
||||||
private Uri mThumbsUri;
|
|
||||||
private Uri mPlaylistsUri;
|
private Uri mPlaylistsUri;
|
||||||
private Uri mFilesUri;
|
private Uri mFilesUri;
|
||||||
private Uri mFilesUriNoNotify;
|
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 {
|
static class MediaBulkDeleter {
|
||||||
StringBuilder whereClause = new StringBuilder();
|
StringBuilder whereClause = new StringBuilder();
|
||||||
ArrayList<String> whereArgs = new ArrayList<String>(100);
|
ArrayList<String> whereArgs = new ArrayList<String>(100);
|
||||||
@@ -1267,9 +1208,6 @@ public class MediaScanner
|
|||||||
processPlayLists();
|
processPlayLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mOriginalCount == 0 && mImagesUri.equals(Images.Media.getContentUri("external")))
|
|
||||||
pruneDeadThumbnailFiles();
|
|
||||||
|
|
||||||
// allow GC to clean up
|
// allow GC to clean up
|
||||||
mPlayLists = null;
|
mPlayLists = null;
|
||||||
mMediaProvider = null;
|
mMediaProvider = null;
|
||||||
@@ -1289,7 +1227,6 @@ public class MediaScanner
|
|||||||
mAudioUri = Audio.Media.getContentUri(volumeName);
|
mAudioUri = Audio.Media.getContentUri(volumeName);
|
||||||
mVideoUri = Video.Media.getContentUri(volumeName);
|
mVideoUri = Video.Media.getContentUri(volumeName);
|
||||||
mImagesUri = Images.Media.getContentUri(volumeName);
|
mImagesUri = Images.Media.getContentUri(volumeName);
|
||||||
mThumbsUri = Images.Thumbnails.getContentUri(volumeName);
|
|
||||||
mFilesUri = Files.getContentUri(volumeName);
|
mFilesUri = Files.getContentUri(volumeName);
|
||||||
mFilesUriNoNotify = mFilesUri.buildUpon().appendQueryParameter("nonotify", "1").build();
|
mFilesUriNoNotify = mFilesUri.buildUpon().appendQueryParameter("nonotify", "1").build();
|
||||||
|
|
||||||
|
|||||||
@@ -44,13 +44,14 @@ import java.util.Hashtable;
|
|||||||
*/
|
*/
|
||||||
public class MiniThumbFile {
|
public class MiniThumbFile {
|
||||||
private static final String TAG = "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;
|
public static final int BYTES_PER_MINTHUMB = 10000;
|
||||||
private static final int HEADER_SIZE = 1 + 8 + 4;
|
private static final int HEADER_SIZE = 1 + 8 + 4;
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
private RandomAccessFile mMiniThumbFile;
|
private RandomAccessFile mMiniThumbFile;
|
||||||
private FileChannel mChannel;
|
private FileChannel mChannel;
|
||||||
private ByteBuffer mBuffer;
|
private ByteBuffer mBuffer;
|
||||||
|
private ByteBuffer mEmptyBuffer;
|
||||||
private static final Hashtable<String, MiniThumbFile> sThumbFiles =
|
private static final Hashtable<String, MiniThumbFile> sThumbFiles =
|
||||||
new Hashtable<String, MiniThumbFile>();
|
new Hashtable<String, MiniThumbFile>();
|
||||||
|
|
||||||
@@ -127,9 +128,10 @@ public class MiniThumbFile {
|
|||||||
return mMiniThumbFile;
|
return mMiniThumbFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiniThumbFile(Uri uri) {
|
private MiniThumbFile(Uri uri) {
|
||||||
mUri = uri;
|
mUri = uri;
|
||||||
mBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
|
mBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
|
||||||
|
mEmptyBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void deactivate() {
|
public synchronized void deactivate() {
|
||||||
@@ -184,6 +186,54 @@ public class MiniThumbFile {
|
|||||||
return 0;
|
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)
|
public synchronized void saveMiniThumbToFile(byte[] data, long id, long magic)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
RandomAccessFile r = miniThumbDataFile();
|
RandomAccessFile r = miniThumbDataFile();
|
||||||
|
|||||||
Reference in New Issue
Block a user