summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/MediaScanner.java181
1 files changed, 85 insertions, 96 deletions
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index c41901b54d73..821a251b2753 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -31,17 +31,16 @@ import android.graphics.BitmapFactory;
import android.mtp.MtpConstants;
import android.net.Uri;
import android.os.Environment;
-import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.MediaStore;
-import android.provider.MediaStore.Files.FileColumns;
-import android.provider.Settings;
import android.provider.MediaStore.Audio;
+import android.provider.MediaStore.Audio.Playlists;
import android.provider.MediaStore.Files;
+import android.provider.MediaStore.Files.FileColumns;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Video;
-import android.provider.MediaStore.Audio.Playlists;
+import android.provider.Settings;
import android.sax.Element;
import android.sax.ElementListener;
import android.sax.RootElement;
@@ -56,10 +55,8 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.Locale;
import libcore.io.ErrnoException;
@@ -372,6 +369,14 @@ public class MediaScanner
}
}
+ private static class PlaylistEntry {
+ String path;
+ long bestmatchid;
+ int bestmatchlevel;
+ }
+
+ private ArrayList<PlaylistEntry> mPlaylistEntries = new ArrayList<PlaylistEntry>();
+
private MediaInserter mMediaInserter;
private ArrayList<FileEntry> mPlayLists;
@@ -1492,93 +1497,83 @@ public class MediaScanner
return result;
}
- private boolean addPlayListEntry(String entry, String playListDirectory,
- Uri uri, ContentValues values, int index, Cursor fileList) {
+ private boolean matchEntries(long rowId, String data) {
+
+ int len = mPlaylistEntries.size();
+ boolean done = true;
+ for (int i = 0; i < len; i++) {
+ PlaylistEntry entry = mPlaylistEntries.get(i);
+ if (entry.bestmatchlevel == Integer.MAX_VALUE) {
+ continue; // this entry has been matched already
+ }
+ done = false;
+ if (data.equalsIgnoreCase(entry.path)) {
+ entry.bestmatchid = rowId;
+ entry.bestmatchlevel = Integer.MAX_VALUE;
+ continue; // no need for path matching
+ }
+
+ int matchLength = matchPaths(data, entry.path);
+ if (matchLength > entry.bestmatchlevel) {
+ entry.bestmatchid = rowId;
+ entry.bestmatchlevel = matchLength;
+ }
+ }
+ return done;
+ }
+ private void cachePlaylistEntry(String line, String playListDirectory) {
+ PlaylistEntry entry = new PlaylistEntry();
// watch for trailing whitespace
- int entryLength = entry.length();
- while (entryLength > 0 && Character.isWhitespace(entry.charAt(entryLength - 1))) entryLength--;
+ int entryLength = line.length();
+ while (entryLength > 0 && Character.isWhitespace(line.charAt(entryLength - 1))) entryLength--;
// path should be longer than 3 characters.
// avoid index out of bounds errors below by returning here.
- if (entryLength < 3) return false;
- if (entryLength < entry.length()) entry = entry.substring(0, entryLength);
+ if (entryLength < 3) return;
+ if (entryLength < line.length()) line = line.substring(0, entryLength);
// does entry appear to be an absolute path?
// look for Unix or DOS absolute paths
- char ch1 = entry.charAt(0);
+ char ch1 = line.charAt(0);
boolean fullPath = (ch1 == '/' ||
- (Character.isLetter(ch1) && entry.charAt(1) == ':' && entry.charAt(2) == '\\'));
+ (Character.isLetter(ch1) && line.charAt(1) == ':' && line.charAt(2) == '\\'));
// if we have a relative path, combine entry with playListDirectory
if (!fullPath)
- entry = playListDirectory + entry;
-
+ line = playListDirectory + line;
+ entry.path = line;
//FIXME - should we look for "../" within the path?
- // best matching MediaFile for the play list entry
- FileEntry bestMatch = null;
-
- // number of rightmost file/directory names for bestMatch
- int bestMatchLength = 0;
-
- if (fileList != null) {
- int count = fileList.getCount();
- // Backing up a little in the cursor helps when the files in the
- // playlist are not in the same order as they are in the database
- // but are still close.
- fileList.move(-1000);
- while(--count >= 0) {
- if (!fileList.moveToNext()) {
- fileList.moveToFirst();
- }
- long rowId = fileList.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
- String path = fileList.getString(FILES_PRESCAN_PATH_COLUMN_INDEX);
- int format = fileList.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
- long lastModified = fileList.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-
- if (path.equalsIgnoreCase(entry)) {
- bestMatch = new FileEntry(rowId, path, lastModified, format);
- break; // don't bother continuing search
- }
+ mPlaylistEntries.add(entry);
+ }
- int matchLength = matchPaths(path, entry);
- if (matchLength > bestMatchLength) {
- bestMatch = new FileEntry(rowId, path, lastModified, format);
- bestMatchLength = matchLength;
- }
+ private void processCachedPlaylist(Cursor fileList, ContentValues values, Uri playlistUri) {
+ fileList.moveToPosition(-1);
+ while (fileList.moveToNext()) {
+ long rowId = fileList.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
+ String data = fileList.getString(FILES_PRESCAN_PATH_COLUMN_INDEX);
+ if (matchEntries(rowId, data)) {
+ break;
}
}
- if (bestMatch == null) {
- return false;
- }
-
- try {
- // check rowid is set. Rowid may be missing if it is inserted by bulkInsert().
- if (bestMatch.mRowId == 0) {
- Cursor c = mMediaProvider.query(mAudioUri, ID_PROJECTION,
- MediaStore.Files.FileColumns.DATA + "=?",
- new String[] { bestMatch.mPath }, null, null);
- if (c != null) {
- if (c.moveToNext()) {
- bestMatch.mRowId = c.getLong(0);
- }
- c.close();
- }
- if (bestMatch.mRowId == 0) {
- return false;
+ int len = mPlaylistEntries.size();
+ int index = 0;
+ for (int i = 0; i < len; i++) {
+ PlaylistEntry entry = mPlaylistEntries.get(i);
+ if (entry.bestmatchlevel > 0) {
+ try {
+ values.clear();
+ values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(index));
+ values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, Long.valueOf(entry.bestmatchid));
+ mMediaProvider.insert(playlistUri, values);
+ index++;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in MediaScanner.processCachedPlaylist()", e);
+ return;
}
}
- // OK, now we are ready to add this to the database
- values.clear();
- values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(index));
- values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, Long.valueOf(bestMatch.mRowId));
- mMediaProvider.insert(uri, values);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in MediaScanner.addPlayListEntry()", e);
- return false;
}
-
- return true;
+ mPlaylistEntries.clear();
}
private void processM3uPlayList(String path, String playListDirectory, Uri uri,
@@ -1590,16 +1585,16 @@ public class MediaScanner
reader = new BufferedReader(
new InputStreamReader(new FileInputStream(f)), 8192);
String line = reader.readLine();
- int index = 0;
+ mPlaylistEntries.clear();
while (line != null) {
// ignore comment lines, which begin with '#'
if (line.length() > 0 && line.charAt(0) != '#') {
- values.clear();
- if (addPlayListEntry(line, playListDirectory, uri, values, index, fileList))
- index++;
+ cachePlaylistEntry(line, playListDirectory);
}
line = reader.readLine();
}
+
+ processCachedPlaylist(fileList, values, uri);
}
} catch (IOException e) {
Log.e(TAG, "IOException in MediaScanner.processM3uPlayList()", e);
@@ -1622,20 +1617,19 @@ public class MediaScanner
reader = new BufferedReader(
new InputStreamReader(new FileInputStream(f)), 8192);
String line = reader.readLine();
- int index = 0;
+ mPlaylistEntries.clear();
while (line != null) {
// ignore comment lines, which begin with '#'
if (line.startsWith("File")) {
int equals = line.indexOf('=');
if (equals > 0) {
- values.clear();
- if (addPlayListEntry(line.substring(equals + 1), playListDirectory,
- uri, values, index, fileList))
- index++;
+ cachePlaylistEntry(line, playListDirectory);
}
}
line = reader.readLine();
}
+
+ processCachedPlaylist(fileList, values, uri);
}
} catch (IOException e) {
Log.e(TAG, "IOException in MediaScanner.processPlsPlayList()", e);
@@ -1653,15 +1647,9 @@ public class MediaScanner
final ContentHandler handler;
String playListDirectory;
- Uri uri;
- Cursor fileList;
- ContentValues values = new ContentValues();
- int index = 0;
public WplHandler(String playListDirectory, Uri uri, Cursor fileList) {
this.playListDirectory = playListDirectory;
- this.uri = uri;
- this.fileList = fileList;
RootElement root = new RootElement("smil");
Element body = root.getChild("body");
@@ -1676,13 +1664,11 @@ public class MediaScanner
public void start(Attributes attributes) {
String path = attributes.getValue("", "src");
if (path != null) {
- values.clear();
- if (addPlayListEntry(path, playListDirectory, uri, values, index, fileList)) {
- index++;
- }
+ cachePlaylistEntry(path, playListDirectory);
}
}
+ @Override
public void end() {
}
@@ -1692,15 +1678,18 @@ public class MediaScanner
}
private void processWplPlayList(String path, String playListDirectory, Uri uri,
- Cursor fileList) {
+ ContentValues values, Cursor fileList) {
FileInputStream fis = null;
try {
File f = new File(path);
if (f.exists()) {
fis = new FileInputStream(f);
+ mPlaylistEntries.clear();
Xml.parse(fis, Xml.findEncodingByName("UTF-8"),
new WplHandler(playListDirectory, uri, fileList).getContentHandler());
+
+ processCachedPlaylist(fileList, values, uri);
}
} catch (SAXException e) {
e.printStackTrace();
@@ -1762,7 +1751,7 @@ public class MediaScanner
} else if (fileType == MediaFile.FILE_TYPE_PLS) {
processPlsPlayList(path, playListDirectory, membersUri, values, fileList);
} else if (fileType == MediaFile.FILE_TYPE_WPL) {
- processWplPlayList(path, playListDirectory, membersUri, fileList);
+ processWplPlayList(path, playListDirectory, membersUri, values, fileList);
}
}
@@ -1800,7 +1789,7 @@ public class MediaScanner
private native final void native_finalize();
/**
- * Releases resouces associated with this MediaScanner object.
+ * Releases resources associated with this MediaScanner object.
* It is considered good practice to call this method when
* one is done using the MediaScanner object. After this method
* is called, the MediaScanner object can no longer be used.