3131import android .mtp .MtpConstants ;
3232import android .net .Uri ;
3333import android .os .Environment ;
34- import android .os .Process ;
3534import android .os .RemoteException ;
3635import android .os .SystemProperties ;
3736import android .provider .MediaStore ;
38- import android .provider .MediaStore .Files .FileColumns ;
39- import android .provider .Settings ;
4037import android .provider .MediaStore .Audio ;
38+ import android .provider .MediaStore .Audio .Playlists ;
4139import android .provider .MediaStore .Files ;
40+ import android .provider .MediaStore .Files .FileColumns ;
4241import android .provider .MediaStore .Images ;
4342import android .provider .MediaStore .Video ;
44- import android .provider .MediaStore . Audio . Playlists ;
43+ import android .provider .Settings ;
4544import android .sax .Element ;
4645import android .sax .ElementListener ;
4746import android .sax .RootElement ;
5655import java .io .IOException ;
5756import java .io .InputStreamReader ;
5857import java .util .ArrayList ;
59- import java .util .HashMap ;
6058import java .util .HashSet ;
6159import java .util .Iterator ;
62- import java .util .LinkedHashMap ;
6360import java .util .Locale ;
6461
6562import libcore .io .ErrnoException ;
@@ -372,6 +369,14 @@ public String toString() {
372369 }
373370 }
374371
372+ private static class PlaylistEntry {
373+ String path ;
374+ long bestmatchid ;
375+ int bestmatchlevel ;
376+ }
377+
378+ private ArrayList <PlaylistEntry > mPlaylistEntries = new ArrayList <PlaylistEntry >();
379+
375380 private MediaInserter mMediaInserter ;
376381
377382 private ArrayList <FileEntry > mPlayLists ;
@@ -1492,93 +1497,83 @@ private int matchPaths(String path1, String path2) {
14921497 return result ;
14931498 }
14941499
1495- private boolean addPlayListEntry (String entry , String playListDirectory ,
1496- Uri uri , ContentValues values , int index , Cursor fileList ) {
1500+ private boolean matchEntries (long rowId , String data ) {
1501+
1502+ int len = mPlaylistEntries .size ();
1503+ boolean done = true ;
1504+ for (int i = 0 ; i < len ; i ++) {
1505+ PlaylistEntry entry = mPlaylistEntries .get (i );
1506+ if (entry .bestmatchlevel == Integer .MAX_VALUE ) {
1507+ continue ; // this entry has been matched already
1508+ }
1509+ done = false ;
1510+ if (data .equalsIgnoreCase (entry .path )) {
1511+ entry .bestmatchid = rowId ;
1512+ entry .bestmatchlevel = Integer .MAX_VALUE ;
1513+ continue ; // no need for path matching
1514+ }
1515+
1516+ int matchLength = matchPaths (data , entry .path );
1517+ if (matchLength > entry .bestmatchlevel ) {
1518+ entry .bestmatchid = rowId ;
1519+ entry .bestmatchlevel = matchLength ;
1520+ }
1521+ }
1522+ return done ;
1523+ }
14971524
1525+ private void cachePlaylistEntry (String line , String playListDirectory ) {
1526+ PlaylistEntry entry = new PlaylistEntry ();
14981527 // watch for trailing whitespace
1499- int entryLength = entry .length ();
1500- while (entryLength > 0 && Character .isWhitespace (entry .charAt (entryLength - 1 ))) entryLength --;
1528+ int entryLength = line .length ();
1529+ while (entryLength > 0 && Character .isWhitespace (line .charAt (entryLength - 1 ))) entryLength --;
15011530 // path should be longer than 3 characters.
15021531 // avoid index out of bounds errors below by returning here.
1503- if (entryLength < 3 ) return false ;
1504- if (entryLength < entry .length ()) entry = entry .substring (0 , entryLength );
1532+ if (entryLength < 3 ) return ;
1533+ if (entryLength < line .length ()) line = line .substring (0 , entryLength );
15051534
15061535 // does entry appear to be an absolute path?
15071536 // look for Unix or DOS absolute paths
1508- char ch1 = entry .charAt (0 );
1537+ char ch1 = line .charAt (0 );
15091538 boolean fullPath = (ch1 == '/' ||
1510- (Character .isLetter (ch1 ) && entry .charAt (1 ) == ':' && entry .charAt (2 ) == '\\' ));
1539+ (Character .isLetter (ch1 ) && line .charAt (1 ) == ':' && line .charAt (2 ) == '\\' ));
15111540 // if we have a relative path, combine entry with playListDirectory
15121541 if (!fullPath )
1513- entry = playListDirectory + entry ;
1514-
1542+ line = playListDirectory + line ;
1543+ entry . path = line ;
15151544 //FIXME - should we look for "../" within the path?
15161545
1517- // best matching MediaFile for the play list entry
1518- FileEntry bestMatch = null ;
1519-
1520- // number of rightmost file/directory names for bestMatch
1521- int bestMatchLength = 0 ;
1522-
1523- if (fileList != null ) {
1524- int count = fileList .getCount ();
1525- // Backing up a little in the cursor helps when the files in the
1526- // playlist are not in the same order as they are in the database
1527- // but are still close.
1528- fileList .move (-1000 );
1529- while (--count >= 0 ) {
1530- if (!fileList .moveToNext ()) {
1531- fileList .moveToFirst ();
1532- }
1533- long rowId = fileList .getLong (FILES_PRESCAN_ID_COLUMN_INDEX );
1534- String path = fileList .getString (FILES_PRESCAN_PATH_COLUMN_INDEX );
1535- int format = fileList .getInt (FILES_PRESCAN_FORMAT_COLUMN_INDEX );
1536- long lastModified = fileList .getLong (FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX );
1537-
1538- if (path .equalsIgnoreCase (entry )) {
1539- bestMatch = new FileEntry (rowId , path , lastModified , format );
1540- break ; // don't bother continuing search
1541- }
1546+ mPlaylistEntries .add (entry );
1547+ }
15421548
1543- int matchLength = matchPaths (path , entry );
1544- if (matchLength > bestMatchLength ) {
1545- bestMatch = new FileEntry (rowId , path , lastModified , format );
1546- bestMatchLength = matchLength ;
1547- }
1549+ private void processCachedPlaylist (Cursor fileList , ContentValues values , Uri playlistUri ) {
1550+ fileList .moveToPosition (-1 );
1551+ while (fileList .moveToNext ()) {
1552+ long rowId = fileList .getLong (FILES_PRESCAN_ID_COLUMN_INDEX );
1553+ String data = fileList .getString (FILES_PRESCAN_PATH_COLUMN_INDEX );
1554+ if (matchEntries (rowId , data )) {
1555+ break ;
15481556 }
15491557 }
15501558
1551- if (bestMatch == null ) {
1552- return false ;
1553- }
1554-
1555- try {
1556- // check rowid is set. Rowid may be missing if it is inserted by bulkInsert().
1557- if (bestMatch .mRowId == 0 ) {
1558- Cursor c = mMediaProvider .query (mAudioUri , ID_PROJECTION ,
1559- MediaStore .Files .FileColumns .DATA + "=?" ,
1560- new String [] { bestMatch .mPath }, null , null );
1561- if (c != null ) {
1562- if (c .moveToNext ()) {
1563- bestMatch .mRowId = c .getLong (0 );
1564- }
1565- c .close ();
1566- }
1567- if (bestMatch .mRowId == 0 ) {
1568- return false ;
1559+ int len = mPlaylistEntries .size ();
1560+ int index = 0 ;
1561+ for (int i = 0 ; i < len ; i ++) {
1562+ PlaylistEntry entry = mPlaylistEntries .get (i );
1563+ if (entry .bestmatchlevel > 0 ) {
1564+ try {
1565+ values .clear ();
1566+ values .put (MediaStore .Audio .Playlists .Members .PLAY_ORDER , Integer .valueOf (index ));
1567+ values .put (MediaStore .Audio .Playlists .Members .AUDIO_ID , Long .valueOf (entry .bestmatchid ));
1568+ mMediaProvider .insert (playlistUri , values );
1569+ index ++;
1570+ } catch (RemoteException e ) {
1571+ Log .e (TAG , "RemoteException in MediaScanner.processCachedPlaylist()" , e );
1572+ return ;
15691573 }
15701574 }
1571- // OK, now we are ready to add this to the database
1572- values .clear ();
1573- values .put (MediaStore .Audio .Playlists .Members .PLAY_ORDER , Integer .valueOf (index ));
1574- values .put (MediaStore .Audio .Playlists .Members .AUDIO_ID , Long .valueOf (bestMatch .mRowId ));
1575- mMediaProvider .insert (uri , values );
1576- } catch (RemoteException e ) {
1577- Log .e (TAG , "RemoteException in MediaScanner.addPlayListEntry()" , e );
1578- return false ;
15791575 }
1580-
1581- return true ;
1576+ mPlaylistEntries .clear ();
15821577 }
15831578
15841579 private void processM3uPlayList (String path , String playListDirectory , Uri uri ,
@@ -1590,16 +1585,16 @@ private void processM3uPlayList(String path, String playListDirectory, Uri uri,
15901585 reader = new BufferedReader (
15911586 new InputStreamReader (new FileInputStream (f )), 8192 );
15921587 String line = reader .readLine ();
1593- int index = 0 ;
1588+ mPlaylistEntries . clear () ;
15941589 while (line != null ) {
15951590 // ignore comment lines, which begin with '#'
15961591 if (line .length () > 0 && line .charAt (0 ) != '#' ) {
1597- values .clear ();
1598- if (addPlayListEntry (line , playListDirectory , uri , values , index , fileList ))
1599- index ++;
1592+ cachePlaylistEntry (line , playListDirectory );
16001593 }
16011594 line = reader .readLine ();
16021595 }
1596+
1597+ processCachedPlaylist (fileList , values , uri );
16031598 }
16041599 } catch (IOException e ) {
16051600 Log .e (TAG , "IOException in MediaScanner.processM3uPlayList()" , e );
@@ -1622,20 +1617,19 @@ private void processPlsPlayList(String path, String playListDirectory, Uri uri,
16221617 reader = new BufferedReader (
16231618 new InputStreamReader (new FileInputStream (f )), 8192 );
16241619 String line = reader .readLine ();
1625- int index = 0 ;
1620+ mPlaylistEntries . clear () ;
16261621 while (line != null ) {
16271622 // ignore comment lines, which begin with '#'
16281623 if (line .startsWith ("File" )) {
16291624 int equals = line .indexOf ('=' );
16301625 if (equals > 0 ) {
1631- values .clear ();
1632- if (addPlayListEntry (line .substring (equals + 1 ), playListDirectory ,
1633- uri , values , index , fileList ))
1634- index ++;
1626+ cachePlaylistEntry (line , playListDirectory );
16351627 }
16361628 }
16371629 line = reader .readLine ();
16381630 }
1631+
1632+ processCachedPlaylist (fileList , values , uri );
16391633 }
16401634 } catch (IOException e ) {
16411635 Log .e (TAG , "IOException in MediaScanner.processPlsPlayList()" , e );
@@ -1653,15 +1647,9 @@ class WplHandler implements ElementListener {
16531647
16541648 final ContentHandler handler ;
16551649 String playListDirectory ;
1656- Uri uri ;
1657- Cursor fileList ;
1658- ContentValues values = new ContentValues ();
1659- int index = 0 ;
16601650
16611651 public WplHandler (String playListDirectory , Uri uri , Cursor fileList ) {
16621652 this .playListDirectory = playListDirectory ;
1663- this .uri = uri ;
1664- this .fileList = fileList ;
16651653
16661654 RootElement root = new RootElement ("smil" );
16671655 Element body = root .getChild ("body" );
@@ -1676,13 +1664,11 @@ public WplHandler(String playListDirectory, Uri uri, Cursor fileList) {
16761664 public void start (Attributes attributes ) {
16771665 String path = attributes .getValue ("" , "src" );
16781666 if (path != null ) {
1679- values .clear ();
1680- if (addPlayListEntry (path , playListDirectory , uri , values , index , fileList )) {
1681- index ++;
1682- }
1667+ cachePlaylistEntry (path , playListDirectory );
16831668 }
16841669 }
16851670
1671+ @ Override
16861672 public void end () {
16871673 }
16881674
@@ -1692,15 +1678,18 @@ ContentHandler getContentHandler() {
16921678 }
16931679
16941680 private void processWplPlayList (String path , String playListDirectory , Uri uri ,
1695- Cursor fileList ) {
1681+ ContentValues values , Cursor fileList ) {
16961682 FileInputStream fis = null ;
16971683 try {
16981684 File f = new File (path );
16991685 if (f .exists ()) {
17001686 fis = new FileInputStream (f );
17011687
1688+ mPlaylistEntries .clear ();
17021689 Xml .parse (fis , Xml .findEncodingByName ("UTF-8" ),
17031690 new WplHandler (playListDirectory , uri , fileList ).getContentHandler ());
1691+
1692+ processCachedPlaylist (fileList , values , uri );
17041693 }
17051694 } catch (SAXException e ) {
17061695 e .printStackTrace ();
@@ -1762,7 +1751,7 @@ private void processPlayList(FileEntry entry, Cursor fileList) throws RemoteExce
17621751 } else if (fileType == MediaFile .FILE_TYPE_PLS ) {
17631752 processPlsPlayList (path , playListDirectory , membersUri , values , fileList );
17641753 } else if (fileType == MediaFile .FILE_TYPE_WPL ) {
1765- processWplPlayList (path , playListDirectory , membersUri , fileList );
1754+ processWplPlayList (path , playListDirectory , membersUri , values , fileList );
17661755 }
17671756 }
17681757
@@ -1800,7 +1789,7 @@ private void processPlayLists() throws RemoteException {
18001789 private native final void native_finalize ();
18011790
18021791 /**
1803- * Releases resouces associated with this MediaScanner object.
1792+ * Releases resources associated with this MediaScanner object.
18041793 * It is considered good practice to call this method when
18051794 * one is done using the MediaScanner object. After this method
18061795 * is called, the MediaScanner object can no longer be used.
0 commit comments