Instead of a raw AIDL interface, give DropBox a Java
interface (android.os.DropBox); move the Binder interface
behind the scenes. Make DropBoxEntry into DropBox.Entry.
Make it possible to get a dropbox from an (Application)Context
with the usual getSystemService(DROPBOX_SERVICE) type thing.
Update the tests accordingly.
diff --git a/services/java/com/android/server/DropBoxService.java b/services/java/com/android/server/DropBoxService.java
index 6c96a46..f4e5ebc 100644
--- a/services/java/com/android/server/DropBoxService.java
+++ b/services/java/com/android/server/DropBoxService.java
@@ -23,8 +23,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
-import android.os.DropBoxEntry;
-import android.os.IDropBox;
+import android.os.DropBox;
import android.os.ParcelFileDescriptor;
import android.os.StatFs;
import android.os.SystemClock;
@@ -32,11 +31,13 @@
import android.text.format.DateFormat;
import android.util.Log;
+import com.android.internal.os.IDropBoxService;
+
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -53,11 +54,12 @@
import java.util.zip.GZIPOutputStream;
/**
- * Implementation of {@link IDropBox} using the filesystem.
+ * Implementation of {@link IDropBoxService} using the filesystem.
+ * Clients use {@link DropBox} to access this service.
*
* {@hide}
*/
-public final class DropBoxService extends IDropBox.Stub {
+public final class DropBoxService extends IDropBoxService.Stub {
private static final String TAG = "DropBoxService";
private static final int DEFAULT_RESERVE_PERCENT = 10;
private static final int DEFAULT_QUOTA_PERCENT = 10;
@@ -129,50 +131,13 @@
mContext.unregisterReceiver(mReceiver);
}
- public void addText(String tag, String data) {
- addData(tag, data.getBytes(), DropBoxEntry.IS_TEXT);
- }
-
- public void addData(String tag, byte[] data, int flags) {
- File temp = null;
- OutputStream out = null;
- try {
- if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
-
- init();
- if (!isTagEnabled(tag)) return;
-
- long max = trimToFit();
- if (data.length > max) {
- Log.w(TAG, "Dropping: " + tag + " (" + data.length + " > " + max + " bytes)");
- // Pass temp = null to createEntry() to leave a tombstone
- } else {
- temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId() + ".tmp");
- out = new FileOutputStream(temp);
- if (data.length > mBlockSize && ((flags & DropBoxEntry.IS_GZIPPED) == 0)) {
- flags = flags | DropBoxEntry.IS_GZIPPED;
- out = new GZIPOutputStream(out);
- }
- out.write(data);
- out.close();
- out = null;
- }
-
- createEntry(temp, tag, flags);
- temp = null;
- } catch (IOException e) {
- Log.e(TAG, "Can't write: " + tag, e);
- } finally {
- try { if (out != null) out.close(); } catch (IOException e) {}
- if (temp != null) temp.delete();
- }
- }
-
- public void addFile(String tag, ParcelFileDescriptor data, int flags) {
+ public void add(DropBox.Entry entry) {
File temp = null;
OutputStream output = null;
+ final String tag = entry.getTag();
try {
- if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
+ int flags = entry.getFlags();
+ if ((flags & DropBox.IS_EMPTY) != 0) throw new IllegalArgumentException();
init();
if (!isTagEnabled(tag)) return;
@@ -180,7 +145,7 @@
long lastTrim = System.currentTimeMillis();
byte[] buffer = new byte[mBlockSize];
- FileInputStream input = new FileInputStream(data.getFileDescriptor());
+ InputStream input = entry.getInputStream();
// First, accumulate up to one block worth of data in memory before
// deciding whether to compress the data or not.
@@ -197,9 +162,9 @@
temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId() + ".tmp");
output = new FileOutputStream(temp);
- if (read == buffer.length && ((flags & DropBoxEntry.IS_GZIPPED) == 0)) {
+ if (read == buffer.length && ((flags & DropBox.IS_GZIPPED) == 0)) {
output = new GZIPOutputStream(output);
- flags = flags | DropBoxEntry.IS_GZIPPED;
+ flags = flags | DropBox.IS_GZIPPED;
}
do {
@@ -234,7 +199,7 @@
Log.e(TAG, "Can't write: " + tag, e);
} finally {
try { if (output != null) output.close(); } catch (IOException e) {}
- try { data.close(); } catch (IOException e) {}
+ entry.close();
if (temp != null) temp.delete();
}
}
@@ -244,7 +209,7 @@
mContentResolver, Settings.Gservices.DROPBOX_TAG_PREFIX + tag));
}
- public synchronized DropBoxEntry getNextEntry(String tag, long millis) {
+ public synchronized DropBox.Entry getNextEntry(String tag, long millis) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.READ_LOGS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("READ_LOGS permission required");
@@ -262,9 +227,11 @@
for (EntryFile entry : list.contents.tailSet(new EntryFile(millis + 1))) {
if (entry.tag == null) continue;
+ if ((entry.flags & DropBox.IS_EMPTY) != 0) {
+ return new DropBox.Entry(entry.tag, entry.timestampMillis);
+ }
try {
- File file = (entry.flags & DropBoxEntry.IS_EMPTY) != 0 ? null : entry.file;
- return new DropBoxEntry(entry.tag, entry.timestampMillis, file, entry.flags);
+ return new DropBox.Entry(entry.tag, entry.timestampMillis, entry.file, entry.flags);
} catch (IOException e) {
Log.e(TAG, "Can't read: " + entry.file, e);
// Continue to next file
@@ -331,25 +298,25 @@
if (entry.file == null) {
pw.println(" (no file)");
continue;
- } else if ((entry.flags & DropBoxEntry.IS_EMPTY) != 0) {
+ } else if ((entry.flags & DropBox.IS_EMPTY) != 0) {
pw.println(" (contents lost)");
continue;
} else {
- pw.print((entry.flags & DropBoxEntry.IS_GZIPPED) != 0 ? " (comopressed " : " (");
- pw.print((entry.flags & DropBoxEntry.IS_TEXT) != 0 ? "text" : "data");
+ pw.print((entry.flags & DropBox.IS_GZIPPED) != 0 ? " (comopressed " : " (");
+ pw.print((entry.flags & DropBox.IS_TEXT) != 0 ? "text" : "data");
pw.format(", %d bytes)", entry.file.length());
pw.println();
}
- if (doFile || (doPrint && (entry.flags & DropBoxEntry.IS_TEXT) == 0)) {
+ if (doFile || (doPrint && (entry.flags & DropBox.IS_TEXT) == 0)) {
if (!doPrint) pw.print(" ");
pw.println(entry.file.getPath());
}
- if ((entry.flags & DropBoxEntry.IS_TEXT) != 0 && (doPrint || !doFile)) {
- DropBoxEntry dbe = null;
+ if ((entry.flags & DropBox.IS_TEXT) != 0 && (doPrint || !doFile)) {
+ DropBox.Entry dbe = null;
try {
- dbe = new DropBoxEntry(
+ dbe = new DropBox.Entry(
entry.tag, entry.timestampMillis, entry.file, entry.flags);
if (doPrint) {
@@ -435,20 +402,20 @@
* @param dir to store file in
* @param tag to use for new log file name
* @param timestampMillis of log entry
- * @param flags for the entry data (from {@link DropBoxEntry})
+ * @param flags for the entry data
* @param blockSize to use for space accounting
* @throws IOException if the file can't be moved
*/
public EntryFile(File temp, File dir, String tag,long timestampMillis,
int flags, int blockSize) throws IOException {
- if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
+ if ((flags & DropBox.IS_EMPTY) != 0) throw new IllegalArgumentException();
this.tag = tag;
this.timestampMillis = timestampMillis;
this.flags = flags;
this.file = new File(dir, Uri.encode(tag) + "@" + timestampMillis +
- ((flags & DropBoxEntry.IS_TEXT) != 0 ? ".txt" : ".dat") +
- ((flags & DropBoxEntry.IS_GZIPPED) != 0 ? ".gz" : ""));
+ ((flags & DropBox.IS_TEXT) != 0 ? ".txt" : ".dat") +
+ ((flags & DropBox.IS_GZIPPED) != 0 ? ".gz" : ""));
if (!temp.renameTo(this.file)) {
throw new IOException("Can't rename " + temp + " to " + this.file);
@@ -466,7 +433,7 @@
public EntryFile(File dir, String tag, long timestampMillis) throws IOException {
this.tag = tag;
this.timestampMillis = timestampMillis;
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
this.file = new File(dir, Uri.encode(tag) + "@" + timestampMillis + ".lost");
this.blocks = 0;
new FileOutputStream(this.file).close();
@@ -486,26 +453,26 @@
if (at < 0) {
this.tag = null;
this.timestampMillis = 0;
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
return;
}
int flags = 0;
this.tag = Uri.decode(name.substring(0, at));
if (name.endsWith(".gz")) {
- flags |= DropBoxEntry.IS_GZIPPED;
+ flags |= DropBox.IS_GZIPPED;
name = name.substring(0, name.length() - 3);
}
if (name.endsWith(".lost")) {
- flags |= DropBoxEntry.IS_EMPTY;
+ flags |= DropBox.IS_EMPTY;
name = name.substring(at + 1, name.length() - 5);
} else if (name.endsWith(".txt")) {
- flags |= DropBoxEntry.IS_TEXT;
+ flags |= DropBox.IS_TEXT;
name = name.substring(at + 1, name.length() - 4);
} else if (name.endsWith(".dat")) {
name = name.substring(at + 1, name.length() - 4);
} else {
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
this.timestampMillis = 0;
return;
}
@@ -523,7 +490,7 @@
public EntryFile(long millis) {
this.tag = null;
this.timestampMillis = millis;
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
this.file = null;
this.blocks = 0;
}
@@ -618,7 +585,7 @@
mAllFiles.blocks -= late.blocks;
FileList tagFiles = mFilesByTag.get(late.tag);
if (tagFiles.contents.remove(late)) tagFiles.blocks -= late.blocks;
- if ((late.flags & DropBoxEntry.IS_EMPTY) == 0) {
+ if ((late.flags & DropBox.IS_EMPTY) == 0) {
enrollEntry(new EntryFile(
late.file, mDropBoxDir, late.tag, t++, late.flags, mBlockSize));
} else {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1a7416a..5f30710 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -296,7 +296,7 @@
try {
Log.i(TAG, "DropBox Service");
- ServiceManager.addService("dropbox",
+ ServiceManager.addService(Context.DROPBOX_SERVICE,
new DropBoxService(context, new File("/data/system/dropbox")));
} catch (Throwable e) {
Log.e(TAG, "Failure starting DropBox Service", e);