1952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor/* 2952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Copyright (C) 2009 The Android Open Source Project 3952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 4952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Licensed under the Apache License, Version 2.0 (the "License"); 5952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * you may not use this file except in compliance with the License. 6952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * You may obtain a copy of the License at 7952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 8952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * http://www.apache.org/licenses/LICENSE-2.0 9952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 10952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Unless required by applicable law or agreed to in writing, software 11952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * distributed under the License is distributed on an "AS IS" BASIS, 12952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * See the License for the specific language governing permissions and 14952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * limitations under the License. 15952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 16952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 17952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorpackage android.os; 18952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 19952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorimport android.util.Log; 20952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 21f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnorimport com.android.internal.os.IDropBoxManagerService; 22952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 23952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorimport java.io.ByteArrayInputStream; 24cc792c4149b7e768fd894c9b268d815a90a60bd0Brad Fitzpatrickimport java.io.Closeable; 25952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorimport java.io.File; 26952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorimport java.io.FileInputStream; 27952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorimport java.io.IOException; 28952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorimport java.io.InputStream; 29952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnorimport java.util.zip.GZIPInputStream; 30952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 31952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor/** 32952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Enqueues chunks of data (from various sources -- application crashes, kernel 33952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * log records, etc.). The queue is size bounded and will drop old data if the 34952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * enqueued data exceeds the maximum size. You can think of this as a 35952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * persistent, system-wide, blob-oriented "logcat". 36952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 37952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * <p>You can obtain an instance of this class by calling 38952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * {@link android.content.Context#getSystemService} 39952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * with {@link android.content.Context#DROPBOX_SERVICE}. 40952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 41f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor * <p>DropBoxManager entries are not sent anywhere directly, but other system 42f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor * services and debugging tools may scan and upload entries for processing. 43952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 44f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnorpublic class DropBoxManager { 45f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor private static final String TAG = "DropBoxManager"; 46f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor private final IDropBoxManagerService mService; 47952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 48952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** Flag value: Entry's content was deleted to save space. */ 49952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public static final int IS_EMPTY = 1; 50952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 51952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** Flag value: Content is human-readable UTF-8 text (can be combined with IS_GZIPPED). */ 52952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public static final int IS_TEXT = 2; 53952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 54e3cfe2d92868513c9524804a362c3c3c8b8cc4e5Dan Egnor /** Flag value: Content can be decompressed with {@link java.util.zip.GZIPOutputStream}. */ 55952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public static final int IS_GZIPPED = 4; 56952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 576e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor /** Flag value for serialization only: Value is a byte array, not a file descriptor */ 586e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor private static final int HAS_BYTE_ARRAY = 8; 596e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor 60952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 61b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * Broadcast Action: This is broadcast when a new entry is added in the dropbox. 62b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * You must hold the {@link android.Manifest.permission#READ_LOGS} permission 63b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * in order to receive this broadcast. 64b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * 65b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * <p class="note">This is a protected intent that can only be sent 66b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * by the system. 67b247536aa3d458750edbc6b45b2348a994d83426Hakan Still */ 68b247536aa3d458750edbc6b45b2348a994d83426Hakan Still public static final String ACTION_DROPBOX_ENTRY_ADDED = 69b247536aa3d458750edbc6b45b2348a994d83426Hakan Still "android.intent.action.DROPBOX_ENTRY_ADDED"; 70b247536aa3d458750edbc6b45b2348a994d83426Hakan Still 71b247536aa3d458750edbc6b45b2348a994d83426Hakan Still /** 72b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * Extra for {@link android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED}: 73b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * string containing the dropbox tag. 74b247536aa3d458750edbc6b45b2348a994d83426Hakan Still */ 75b247536aa3d458750edbc6b45b2348a994d83426Hakan Still public static final String EXTRA_TAG = "tag"; 76b247536aa3d458750edbc6b45b2348a994d83426Hakan Still 77b247536aa3d458750edbc6b45b2348a994d83426Hakan Still /** 78b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * Extra for {@link android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED}: 79b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * long integer value containing time (in milliseconds since January 1, 1970 00:00:00 UTC) 80b247536aa3d458750edbc6b45b2348a994d83426Hakan Still * when the entry was created. 81b247536aa3d458750edbc6b45b2348a994d83426Hakan Still */ 82b247536aa3d458750edbc6b45b2348a994d83426Hakan Still public static final String EXTRA_TIME = "time"; 83b247536aa3d458750edbc6b45b2348a994d83426Hakan Still 84b247536aa3d458750edbc6b45b2348a994d83426Hakan Still /** 85952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * A single entry retrieved from the drop box. 86952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * This may include a reference to a stream, so you must call 87952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * {@link #close()} when you are done using it. 88952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 89cc792c4149b7e768fd894c9b268d815a90a60bd0Brad Fitzpatrick public static class Entry implements Parcelable, Closeable { 90952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor private final String mTag; 91952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor private final long mTimeMillis; 92952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 93952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor private final byte[] mData; 94952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor private final ParcelFileDescriptor mFileDescriptor; 95952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor private final int mFlags; 96952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 97952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** Create a new empty Entry with no contents. */ 98952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry(String tag, long millis) { 996e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (tag == null) throw new NullPointerException("tag == null"); 1006e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor 1016e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTag = tag; 1026e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTimeMillis = millis; 1036e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mData = null; 1046e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFileDescriptor = null; 1056e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFlags = IS_EMPTY; 106952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 107952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 108952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** Create a new Entry with plain text contents. */ 109952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry(String tag, long millis, String text) { 1106e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (tag == null) throw new NullPointerException("tag == null"); 1116e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (text == null) throw new NullPointerException("text == null"); 1126e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor 1136e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTag = tag; 1146e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTimeMillis = millis; 1156e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mData = text.getBytes(); 1166e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFileDescriptor = null; 1176e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFlags = IS_TEXT; 118952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 119952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 120952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 121952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Create a new Entry with byte array contents. 122952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * The data array must not be modified after creating this entry. 123952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 124952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry(String tag, long millis, byte[] data, int flags) { 1256e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (tag == null) throw new NullPointerException("tag == null"); 1266e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (((flags & IS_EMPTY) != 0) != (data == null)) { 1276e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor throw new IllegalArgumentException("Bad flags: " + flags); 1286e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor } 1296e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor 1306e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTag = tag; 1316e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTimeMillis = millis; 1326e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mData = data; 1336e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFileDescriptor = null; 1346e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFlags = flags; 135952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 136952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 137952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 138952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Create a new Entry with streaming data contents. 139952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Takes ownership of the ParcelFileDescriptor. 140952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 141952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry(String tag, long millis, ParcelFileDescriptor data, int flags) { 1426e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (tag == null) throw new NullPointerException("tag == null"); 1436e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (((flags & IS_EMPTY) != 0) != (data == null)) { 1446e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor throw new IllegalArgumentException("Bad flags: " + flags); 1456e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor } 1466e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor 1476e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTag = tag; 1486e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mTimeMillis = millis; 1496e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mData = null; 1506e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFileDescriptor = data; 1516e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFlags = flags; 152952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 153952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 154952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 155952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Create a new Entry with the contents read from a file. 156952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * The file will be read when the entry's contents are requested. 157952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 158952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry(String tag, long millis, File data, int flags) throws IOException { 1596e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (tag == null) throw new NullPointerException("tag == null"); 1606e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if ((flags & IS_EMPTY) != 0) throw new IllegalArgumentException("Bad flags: " + flags); 161952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 162952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor mTag = tag; 163952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor mTimeMillis = millis; 1646e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mData = null; 1656e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFileDescriptor = ParcelFileDescriptor.open(data, ParcelFileDescriptor.MODE_READ_ONLY); 166952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor mFlags = flags; 167952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 168952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 169952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** Close the input stream associated with this entry. */ 170952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public void close() { 171952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor try { if (mFileDescriptor != null) mFileDescriptor.close(); } catch (IOException e) { } 172952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 173952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 174952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** @return the tag originally attached to the entry. */ 175952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public String getTag() { return mTag; } 176952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 177952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** @return time when the entry was originally created. */ 178952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public long getTimeMillis() { return mTimeMillis; } 179952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 18095173b14d65cd04ec88d4384b41a80319e432d0bBrad Fitzpatrick /** @return flags describing the content returned by {@link #getInputStream()}. */ 181952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public int getFlags() { return mFlags & ~IS_GZIPPED; } // getInputStream() decompresses. 182952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 183952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 184952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param maxBytes of string to return (will truncate at this length). 185952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @return the uncompressed text contents of the entry, null if the entry is not text. 186952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 187952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public String getText(int maxBytes) { 188952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor if ((mFlags & IS_TEXT) == 0) return null; 189952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor if (mData != null) return new String(mData, 0, Math.min(maxBytes, mData.length)); 190952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 191952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor InputStream is = null; 192952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor try { 193952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor is = getInputStream(); 1946e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (is == null) return null; 195952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor byte[] buf = new byte[maxBytes]; 196e9f18815218b2ff1f01ea16f2eb0dd17504a9cf3Christian Lindeberg int readBytes = 0; 197e9f18815218b2ff1f01ea16f2eb0dd17504a9cf3Christian Lindeberg int n = 0; 198e9f18815218b2ff1f01ea16f2eb0dd17504a9cf3Christian Lindeberg while (n >= 0 && (readBytes += n) < maxBytes) { 199e9f18815218b2ff1f01ea16f2eb0dd17504a9cf3Christian Lindeberg n = is.read(buf, readBytes, maxBytes - readBytes); 200e9f18815218b2ff1f01ea16f2eb0dd17504a9cf3Christian Lindeberg } 201e9f18815218b2ff1f01ea16f2eb0dd17504a9cf3Christian Lindeberg return new String(buf, 0, readBytes); 202952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } catch (IOException e) { 203952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor return null; 204952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } finally { 205952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor try { if (is != null) is.close(); } catch (IOException e) {} 206952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 207952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 208952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 209952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** @return the uncompressed contents of the entry, or null if the contents were lost */ 210952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public InputStream getInputStream() throws IOException { 211952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor InputStream is; 212952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor if (mData != null) { 213952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor is = new ByteArrayInputStream(mData); 214952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } else if (mFileDescriptor != null) { 215952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor is = new ParcelFileDescriptor.AutoCloseInputStream(mFileDescriptor); 216952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } else { 217952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor return null; 218952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 219952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is; 220952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 221952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 222952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public static final Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator() { 223952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry[] newArray(int size) { return new Entry[size]; } 224952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry createFromParcel(Parcel in) { 2256e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor String tag = in.readString(); 2266e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor long millis = in.readLong(); 2276e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor int flags = in.readInt(); 2286e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if ((flags & HAS_BYTE_ARRAY) != 0) { 2296e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor return new Entry(tag, millis, in.createByteArray(), flags & ~HAS_BYTE_ARRAY); 2306e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor } else { 2316e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor return new Entry(tag, millis, in.readFileDescriptor(), flags); 2326e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor } 233952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 234952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor }; 235952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 236952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public int describeContents() { 237952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor return mFileDescriptor != null ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0; 238952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 239952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 240952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public void writeToParcel(Parcel out, int flags) { 241952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor out.writeString(mTag); 242952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor out.writeLong(mTimeMillis); 243952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor if (mFileDescriptor != null) { 2446e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor out.writeInt(mFlags & ~HAS_BYTE_ARRAY); // Clear bit just to be safe 2456e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor mFileDescriptor.writeToParcel(out, flags); 246952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } else { 2476e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor out.writeInt(mFlags | HAS_BYTE_ARRAY); 2486e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor out.writeByteArray(mData); 249952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 250952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 251952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 252952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 253952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** {@hide} */ 254f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor public DropBoxManager(IDropBoxManagerService service) { mService = service; } 255952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 256952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 257952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Create a dummy instance for testing. All methods will fail unless 258952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * overridden with an appropriate mock implementation. To obtain a 259952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * functional instance, use {@link android.content.Context#getSystemService}. 260952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 261f18a01c77e78209b74e34d05cfb352fa4a92db5fDan Egnor protected DropBoxManager() { mService = null; } 262952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 263952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 264952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Stores human-readable text. The data may be discarded eventually (or even 265952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * immediately) if space is limited, or ignored entirely if the tag has been 266952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * blocked (see {@link #isTagEnabled}). 267952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 268952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param tag describing the type of entry being stored 269952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param data value to store 270952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 271952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public void addText(String tag, String data) { 272952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor try { mService.add(new Entry(tag, 0, data)); } catch (RemoteException e) {} 273952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 274952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 275952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 276952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Stores binary data, which may be ignored or discarded as with {@link #addText}. 277952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 278952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param tag describing the type of entry being stored 279952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param data value to store 280952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param flags describing the data 281952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 282952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public void addData(String tag, byte[] data, int flags) { 2836e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (data == null) throw new NullPointerException("data == null"); 284952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor try { mService.add(new Entry(tag, 0, data, flags)); } catch (RemoteException e) {} 285952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 286952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 287952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 288eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor * Stores the contents of a file, which may be ignored or discarded as with 289eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor * {@link #addText}. 290952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 291952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param tag describing the type of entry being stored 292eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor * @param file to read from 293952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param flags describing the data 294eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor * @throws IOException if the file can't be opened 295952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 296eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor public void addFile(String tag, File file, int flags) throws IOException { 2976e6d60d4c85ce440d9ef5e5f36e708ed0ced65c6Dan Egnor if (file == null) throw new NullPointerException("file == null"); 298eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor Entry entry = new Entry(tag, 0, file, flags); 299eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor try { 30014418945bdc7a9c2e1cba8deaac5cb6dddfd6412Brad Fitzpatrick mService.add(entry); 301eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor } catch (RemoteException e) { 302eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor // ignore 303eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor } finally { 304eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor entry.close(); 305eb7a7d57ca50f85b054edadab766b51ff22a2dfdDan Egnor } 306952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 307952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 308952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 309952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * Checks any blacklists (set in system settings) to see whether a certain 310952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * tag is allowed. Entries with disabled tags will be dropped immediately, 311952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * so you can save the work of actually constructing and sending the data. 312952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 313952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param tag that would be used in {@link #addText} or {@link #addFile} 314952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @return whether events with that tag would be accepted 315952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 316952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public boolean isTagEnabled(String tag) { 317952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor try { return mService.isTagEnabled(tag); } catch (RemoteException e) { return false; } 318952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 319952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 320952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor /** 32130f5c8fede241e7560f4a33e48af3a4627fd5efcBrad Fitzpatrick * Gets the next entry from the drop box <em>after</em> the specified time. 32230f5c8fede241e7560f4a33e48af3a4627fd5efcBrad Fitzpatrick * Requires <code>android.permission.READ_LOGS</code>. You must always call 323952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * {@link Entry#close()} on the return value! 324952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * 325952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param tag of entry to look for, null for all tags 326952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @param msec time of the last entry seen 327952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor * @return the next entry, or null if there are no more entries 328952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor */ 329952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor public Entry getNextEntry(String tag, long msec) { 330952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor try { return mService.getNextEntry(tag, msec); } catch (RemoteException e) { return null; } 331952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor } 332952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor 333952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor // TODO: It may be useful to have some sort of notification mechanism 334952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor // when data is added to the dropbox, for demand-driven readers -- 335952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor // for now readers need to poll the dropbox to find new data. 336952402704a175ba27f6c89dff1ada634c5ce5626Dan Egnor} 337