From d0fbb0eed03e64c7aaaae53ab292bfd988819289 Mon Sep 17 00:00:00 2001 From: Adrian Ulrich Date: Sat, 11 Aug 2018 10:14:10 +0200 Subject: [PATCH] Add minor PlaylistObserver bugfixes. * use mHandler.quit() on lower API versions * do not trust filesystem version of playlists if folder is not writable * disable debug logger --- .../android/vanilla/PlaylistObserver.java | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java b/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java index c1f78b11..22804d20 100644 --- a/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java +++ b/app/src/main/java/ch/blinkenlights/android/vanilla/PlaylistObserver.java @@ -25,6 +25,7 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.os.Build; import android.os.Environment; import android.os.FileObserver; import android.os.Handler; @@ -46,6 +47,10 @@ import android.util.Log; public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callback { + /** + * Whether or not to write debug logs. + */ + private final static boolean DEBUG = false; /** * Bits for mSyncMode */ @@ -111,6 +116,16 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper(), this); + // Create playlists directory if not existing. + if ((mSyncMode & SYNC_MODE_EXPORT) != 0) { + try { + mPlaylists.mkdir(); + } catch (Exception e) { + // don't care: code will ignore events + // if mPlaylists is not a (writable) dir. + } + } + // Register to receive media library events. MediaLibrary.registerLibraryObserver(mLibraryObserver); // Create and start directory observer. @@ -129,11 +144,36 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba MediaLibrary.unregisterLibraryObserver(mLibraryObserver); mFileObserver.stopWatching(); - mHandlerThread.quitSafely(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + mHandlerThread.quitSafely(); + } else { + mHandlerThread.quit(); + } mHandlerThread = null; mHandler = null; } + /** + * Whether or not to handle (or drop) any events received. + * This has the same effect as unregistering, without actually + * unregistering. The function prevents false events from + * being handled if our playlists folder becomes 'suspect'. + */ + private boolean shouldDispatch() { + // This is so sad, but java.nio.file is only available since API 26, + // so we are stuck with java being java. + boolean deny = false; + try { + File f = File.createTempFile("vanilla-write-check", null, mPlaylists); + f.delete(); + } catch (Exception e) { + // don't care about the exact error: as long as the write failed, + // we should not assume that we could write anything else. + deny = true; + } + return !deny; + } + /** * SQLiteHelper onCreate */ @@ -324,9 +364,6 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba final File m3u = getFileForName(mPlaylists, asM3u(name)); - if (!mPlaylists.isDirectory()) - mPlaylists.mkdir(); - PrintWriter pw = null; QueryTask query = MediaUtils.buildPlaylistQuery(id, Song.FILLED_PLAYLIST_PROJECTION); Cursor cursor = query.runQuery(mContext); @@ -537,6 +574,9 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba if (type != LibraryObserver.Type.PLAYLIST || ongoing) return; + if (!shouldDispatch()) + return; + int msg = MSG_DUMP_M3U; // Default: export this playlist ID. if (id == LibraryObserver.Value.UNKNOWN) { // An unknown (all?) playlist was modified: dump all to M3U @@ -568,6 +608,9 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba if (!isM3uFilename(dirent)) return; + if (!shouldDispatch()) + return; + if ((event & (FileObserver.MOVED_FROM | FileObserver.DELETE)) != 0) { // A M3U vanished, do a full scan. XT("FileObserver::onEvent DELETE of "+dirent+" triggers FULL_SYNC_SCAN"); @@ -583,10 +626,11 @@ public class PlaylistObserver extends SQLiteOpenHelper implements Handler.Callba } private void XT(String s) { - try(PrintWriter pw = new PrintWriter(new FileOutputStream(new File("/sdcard/playlist-observer.txt"), true))) { - pw.println(System.currentTimeMillis()/1000+": "+s); - Log.v("VanillaMusic", "XTRACE: "+s); - } catch(Exception e) { + if (DEBUG) { + try(PrintWriter pw = new PrintWriter(new FileOutputStream(new File("/sdcard/playlist-observer.txt"), true))) { + pw.println(System.currentTimeMillis()/1000+": "+s); + Log.v("VanillaMusic", "XTRACE: "+s); + } catch(Exception e) {} } } }