improve quickscan

This commit is contained in:
Adrian Ulrich 2017-01-15 17:16:16 +01:00
parent bb2e707844
commit d2b5f931d2
2 changed files with 98 additions and 36 deletions

View File

@ -42,7 +42,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@string/media_scan_start">
<requestFocus />
</Button>
<TextView
@ -76,6 +75,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</TableRow>
</TableLayout>
<Button
android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@android:string/cancel">
</Button>
<TextView
@ -85,14 +91,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
android:layout_height="wrap_content"
android:text="@string/empty" />
<Button
android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@android:string/cancel">
<requestFocus />
</Button>
</LinearLayout>

View File

@ -68,7 +68,15 @@ public class MediaScanner implements Handler.Callback {
/**
* The id we are using for the scan notification
*/
private int NOTIFICATION_ID = 56162;
private static final int NOTIFICATION_ID = 56162;
/**
* The preference key to store the last mtime
*/
private static final String PREF_KEY_MTIME = "native_last_mtime";
/**
* The preference key to store the native audio size
*/
private static final String PREF_KEY_DBCOUNT = "native_audio_db_count";
MediaScanner(Context context, MediaLibraryBackend backend) {
mContext = context;
@ -117,10 +125,8 @@ public class MediaScanner implements Handler.Callback {
* @param delay how many ms we should wait (used to coalesce multiple calls)
*/
public void startQuickScan(int delay) {
if (!mHandler.hasMessages(MSG_SCAN_RPC)) {
mScanPlan.addNextStep(RPC_NATIVE_VRFY, null)
.addOptionalStep(RPC_LIBRARY_VRFY, null); // only runs if previous scan found no change
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SCAN_RPC, RPC_KICKSTART, 0), delay);
if (!mHandler.hasMessages(MSG_GUESS_QUICKSCAN) && !mHandler.hasMessages(MSG_SCAN_RPC)) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_GUESS_QUICKSCAN, 0, 0), delay);
}
}
@ -139,7 +145,7 @@ public class MediaScanner implements Handler.Callback {
public void flushDatabase() {
mBackend.delete(MediaLibrary.TABLE_SONGS, null, null);
mBackend.cleanOrphanedEntries(false); // -> keep playlists
getSetScanMark(0);
getSetPreference(PREF_KEY_MTIME, 0);
}
/**
@ -151,14 +157,15 @@ public class MediaScanner implements Handler.Callback {
return mScanPlan.getStatistics();
}
private static final int MSG_SCAN_RPC = 0;
private static final int MSG_SCAN_FINISHED = 1;
private static final int MSG_NOTIFY_CHANGE = 2;
private static final int RPC_KICKSTART = 100;
private static final int RPC_READ_DIR = 101;
private static final int RPC_INSPECT_FILE = 102;
private static final int RPC_LIBRARY_VRFY = 103;
private static final int RPC_NATIVE_VRFY = 104;
private static final int MSG_SCAN_RPC = 0;
private static final int MSG_SCAN_FINISHED = 1;
private static final int MSG_NOTIFY_CHANGE = 2;
private static final int MSG_GUESS_QUICKSCAN = 3;
private static final int RPC_KICKSTART = 100;
private static final int RPC_READ_DIR = 101;
private static final int RPC_INSPECT_FILE = 102;
private static final int RPC_LIBRARY_VRFY = 103;
private static final int RPC_NATIVE_VRFY = 104;
@Override
public boolean handleMessage(Message message) {
@ -177,9 +184,13 @@ public class MediaScanner implements Handler.Callback {
updateNotification(false);
break;
}
case MSG_GUESS_QUICKSCAN: {
guessQuickScanPlan();
break;
}
case RPC_KICKSTART: {
// a new scan was triggered: check if this is a 'initial / from scratch' scan
if (!mIsInitialScan && getSetScanMark(-1) == 0) {
if (!mIsInitialScan && getSetPreference(PREF_KEY_MTIME, -1) == 0) {
mIsInitialScan = true;
}
break;
@ -254,6 +265,42 @@ public class MediaScanner implements Handler.Callback {
}
}
/**
* Checks the state of the native media db to deceide if we are going to
* check for deleted or new/modified items
*/
private void guessQuickScanPlan() {
int lastSeenDbSize = getSetPreference(PREF_KEY_DBCOUNT, -1);
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String[] projection = { "COUNT(*)" };
Cursor cursor = null;
try {
cursor = mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, null, null);
} catch (SecurityException e) {
Log.e("VanillaMusic", "rpcObserveRemoval query failed: "+e);
}
if (cursor == null)
return;
cursor.moveToFirst();
int currentDbSize = cursor.getInt(0);
cursor.close();
// Store new db size
getSetPreference(PREF_KEY_DBCOUNT, currentDbSize);
if (currentDbSize < lastSeenDbSize) {
// db is smaller! check for deleted files
mScanPlan.addNextStep(RPC_LIBRARY_VRFY, null);
} else {
// same size or more entries -> check only for modifications
mScanPlan.addNextStep(RPC_NATIVE_VRFY, null);
}
mHandler.sendMessage(mHandler.obtainMessage(MSG_SCAN_RPC, RPC_KICKSTART, 0));
}
/**
* Scans the android library, inspecting every found file
*
@ -262,7 +309,7 @@ public class MediaScanner implements Handler.Callback {
*/
private void rpcNativeVerify(Cursor cursor, int mtime) {
if (cursor == null) {
mtime = getSetScanMark(-1); // starting a new scan -> read stored mtime from preferences
mtime = getSetPreference(PREF_KEY_MTIME, -1); // starting a new scan -> read stored mtime from preferences
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0 AND "+ MediaStore.MediaColumns.DATE_MODIFIED +" > " + mtime;
String sort = MediaStore.MediaColumns.DATE_MODIFIED;
String[] projection = { MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DATE_MODIFIED };
@ -286,12 +333,11 @@ public class MediaScanner implements Handler.Callback {
}
} else {
cursor.close();
getSetScanMark(mtime);
getSetPreference(PREF_KEY_MTIME, mtime);
Log.v("VanillaMusic", "NativeLibraryScanner finished, mtime mark is now at "+mtime);
}
}
/**
* Scans every file in our own library and checks for changes
*
@ -485,12 +531,11 @@ public class MediaScanner implements Handler.Callback {
* @param newVal the new value to store, ignored if < 0
* @return the value previously set, or 0 as a default
*/
private int getSetScanMark(int newVal) {
final String prefKey = "native_last_mtime";
private int getSetPreference(String prefKey, int newVal) {
SharedPreferences sharedPref = mContext.getSharedPreferences("scanner_preferences", Context.MODE_PRIVATE);
int oldVal = sharedPref.getInt(prefKey, 0);
if (newVal >= 0) {
if (newVal >= 0 && newVal != oldVal) {
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(prefKey, newVal);
editor.apply();
@ -503,13 +548,16 @@ public class MediaScanner implements Handler.Callback {
// MediaScanPlan describes how we are going to perform the media scan
class MediaScanPlan {
class Step {
private static final int MODE_NORMAL = 1; // this step is always run
private static final int MODE_OPTIONAL = 2; // only run if previous step found NO changes
private static final int MODE_CHAINED = 3; // only run if previous step DID find changes
int msg;
Object arg;
boolean optional;
Step (int msg, Object arg, boolean optional) {
int mode;
Step (int msg, Object arg, int mode) {
this.msg = msg;
this.arg = arg;
this.optional = optional;
this.mode = mode;
}
}
@ -571,7 +619,7 @@ public class MediaScanner implements Handler.Callback {
* @param arg the argument to msg
*/
MediaScanPlan addNextStep(int msg, Object arg) {
mSteps.add(new Step(msg, arg, false));
mSteps.add(new Step(msg, arg, Step.MODE_NORMAL));
return this;
}
@ -583,7 +631,19 @@ public class MediaScanner implements Handler.Callback {
* @param arg the argument to msg
*/
MediaScanPlan addOptionalStep(int msg, Object arg) {
mSteps.add(new Step(msg, arg, true));
mSteps.add(new Step(msg, arg, Step.MODE_OPTIONAL));
return this;
}
/**
* Adds a chained step to our plan. This will ONLY
* run if the previous step caused database changes
*
* @param msg the message to add
* @param arg the argument to msg
*/
MediaScanPlan addChainedStep(int msg, Object arg) {
mSteps.add(new Step(msg, arg, Step.MODE_CHAINED));
return this;
}
@ -595,7 +655,11 @@ public class MediaScanner implements Handler.Callback {
Step getNextStep() {
Step next = (mSteps.size() != 0 ? mSteps.remove(0) : null);
if (next != null) {
if (next.optional && mStats.changed != 0) {
if (next.mode == Step.MODE_OPTIONAL && mStats.changed != 0) {
next = null;
mSteps.clear();
}
if (next.mode == Step.MODE_CHAINED && mStats.changed == 0) {
next = null;
mSteps.clear();
}