diff options
| author | Dan Egnor <egnor@google.com> | 2010-03-24 17:48:20 -0700 |
|---|---|---|
| committer | Dan Egnor <egnor@google.com> | 2010-03-24 17:48:20 -0700 |
| commit | 3a8b0c18a49c017ecfde8ebf4eb4bb5181ac6fef (patch) | |
| tree | ef23dd3d6f7bc385025977c79fc1808ee29ca02c | |
| parent | 3e8b72ac6e2e5237c21f7af28adaa595dd68ffe5 (diff) | |
| download | frameworks_base-3a8b0c18a49c017ecfde8ebf4eb4bb5181ac6fef.zip frameworks_base-3a8b0c18a49c017ecfde8ebf4eb4bb5181ac6fef.tar.gz frameworks_base-3a8b0c18a49c017ecfde8ebf4eb4bb5181ac6fef.tar.bz2 | |
Limit DropBox storage to 1000 files (by default).
Also does trimming asynchronously (not directly in the broadcast receiver).
Bug: 2541253
Change-Id: I7daf8bc618e2dce68a98571f5f7fbce4df1d6a76
3 files changed, 78 insertions, 11 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2ba38c2..fc207ac 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2903,6 +2903,12 @@ public final class Settings { public static final String DROPBOX_AGE_SECONDS = "dropbox_age_seconds"; /** + * Maximum number of entry files which {@link android.os.IDropBox} will keep around. + * @hide + */ + public static final String DROPBOX_MAX_FILES = + "dropbox_max_files"; + /** * Maximum amount of disk space used by {@link android.os.IDropBox} no matter what. * @hide */ diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/java/com/android/server/DropBoxManagerService.java index b38f1d2..0de11c6 100644 --- a/services/java/com/android/server/DropBoxManagerService.java +++ b/services/java/com/android/server/DropBoxManagerService.java @@ -61,10 +61,11 @@ import java.util.zip.GZIPOutputStream; */ public final class DropBoxManagerService extends IDropBoxManagerService.Stub { private static final String TAG = "DropBoxManagerService"; - private static final int DEFAULT_RESERVE_PERCENT = 10; - private static final int DEFAULT_QUOTA_PERCENT = 10; - private static final int DEFAULT_QUOTA_KB = 5 * 1024; private static final int DEFAULT_AGE_SECONDS = 3 * 86400; + private static final int DEFAULT_MAX_FILES = 1000; + private static final int DEFAULT_QUOTA_KB = 5 * 1024; + private static final int DEFAULT_QUOTA_PERCENT = 10; + private static final int DEFAULT_RESERVE_PERCENT = 10; private static final int QUOTA_RESCAN_MILLIS = 5000; private static final boolean PROFILE_DUMP = false; @@ -99,12 +100,20 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub { @Override public void onReceive(Context context, Intent intent) { mCachedQuotaUptimeMillis = 0; // Force a re-check of quota size - try { - init(); - trimToFit(); - } catch (IOException e) { - Slog.e(TAG, "Can't init", e); - } + + // Run the initialization in the background (not this main thread). + // The init() and trimToFit() methods are synchronized, so they still + // block other users -- but at least the onReceive() call can finish. + new Thread() { + public void run() { + try { + init(); + trimToFit(); + } catch (IOException e) { + Slog.e(TAG, "Can't init", e); + } + } + }.start(); } }; @@ -631,10 +640,12 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub { int ageSeconds = Settings.Secure.getInt(mContentResolver, Settings.Secure.DROPBOX_AGE_SECONDS, DEFAULT_AGE_SECONDS); + int maxFiles = Settings.Secure.getInt(mContentResolver, + Settings.Secure.DROPBOX_MAX_FILES, DEFAULT_MAX_FILES); long cutoffMillis = System.currentTimeMillis() - ageSeconds * 1000; while (!mAllFiles.contents.isEmpty()) { EntryFile entry = mAllFiles.contents.first(); - if (entry.timestampMillis > cutoffMillis) break; + if (entry.timestampMillis > cutoffMillis && mAllFiles.contents.size() < maxFiles) break; FileList tag = mFilesByTag.get(entry.tag); if (tag != null && tag.contents.remove(entry)) tag.blocks -= entry.blocks; @@ -673,7 +684,7 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub { // A single circular buffer (a la logcat) would be simpler, but this // way we can handle fat/bursty data (like 1MB+ bugreports, 300KB+ // kernel crash dumps, and 100KB+ ANR reports) without swamping small, - // well-behaved data // streams (event statistics, profile data, etc). + // well-behaved data streams (event statistics, profile data, etc). // // Deleted files are replaced with zero-length tombstones to mark what // was lost. Tombstones are expunged by age (see above). diff --git a/services/tests/servicestests/src/com/android/server/DropBoxTest.java b/services/tests/servicestests/src/com/android/server/DropBoxTest.java index 3842d45..78a90fb 100644 --- a/services/tests/servicestests/src/com/android/server/DropBoxTest.java +++ b/services/tests/servicestests/src/com/android/server/DropBoxTest.java @@ -39,6 +39,7 @@ public class DropBoxTest extends AndroidTestCase { public void tearDown() throws Exception { ContentResolver cr = getContext().getContentResolver(); Settings.Secure.putString(cr, Settings.Secure.DROPBOX_AGE_SECONDS, ""); + Settings.Secure.putString(cr, Settings.Secure.DROPBOX_MAX_FILES, ""); Settings.Secure.putString(cr, Settings.Secure.DROPBOX_QUOTA_KB, ""); Settings.Secure.putString(cr, Settings.Secure.DROPBOX_TAG_PREFIX + "DropBoxTest", ""); } @@ -457,6 +458,55 @@ public class DropBoxTest extends AndroidTestCase { e0.close(); } + public void testFileCountLimits() throws Exception { + File dir = getEmptyDir("testFileCountLimits"); + + DropBoxManagerService service = new DropBoxManagerService(getContext(), dir); + DropBoxManager dropbox = new DropBoxManager(service); + dropbox.addText("DropBoxTest", "TEST0"); + dropbox.addText("DropBoxTest", "TEST1"); + dropbox.addText("DropBoxTest", "TEST2"); + dropbox.addText("DropBoxTest", "TEST3"); + dropbox.addText("DropBoxTest", "TEST4"); + dropbox.addText("DropBoxTest", "TEST5"); + + // Verify 6 files added + DropBoxManager.Entry e0 = dropbox.getNextEntry(null, 0); + DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis()); + DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis()); + DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis()); + DropBoxManager.Entry e4 = dropbox.getNextEntry(null, e3.getTimeMillis()); + DropBoxManager.Entry e5 = dropbox.getNextEntry(null, e4.getTimeMillis()); + assertTrue(null == dropbox.getNextEntry(null, e5.getTimeMillis())); + assertEquals("TEST0", e0.getText(80)); + assertEquals("TEST5", e5.getText(80)); + + e0.close(); + e1.close(); + e2.close(); + e3.close(); + e4.close(); + e5.close(); + + // Limit to 3 files and add one more entry + ContentResolver cr = getContext().getContentResolver(); + Settings.Secure.putString(cr, Settings.Secure.DROPBOX_MAX_FILES, "3"); + dropbox.addText("DropBoxTest", "TEST6"); + + // Verify only 3 files left + DropBoxManager.Entry f0 = dropbox.getNextEntry(null, 0); + DropBoxManager.Entry f1 = dropbox.getNextEntry(null, f0.getTimeMillis()); + DropBoxManager.Entry f2 = dropbox.getNextEntry(null, f1.getTimeMillis()); + assertTrue(null == dropbox.getNextEntry(null, f2.getTimeMillis())); + assertEquals("TEST4", f0.getText(80)); + assertEquals("TEST5", f1.getText(80)); + assertEquals("TEST6", f2.getText(80)); + + f0.close(); + f1.close(); + f2.close(); + } + public void testCreateDropBoxManagerWithInvalidDirectory() throws Exception { // If created with an invalid directory, the DropBoxManager should suffer quietly // and fail all operations (this is how it survives a full disk). |
