BackupDataInput.java revision 4e14a829129feee14ebe453f61a124784c870610
11cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato/* 21cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * Copyright (C) 2009 The Android Open Source Project 31cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * 41cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License"); 51cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * you may not use this file except in compliance with the License. 61cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * You may obtain a copy of the License at 71cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * 81cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * http://www.apache.org/licenses/LICENSE-2.0 91cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * 101cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * Unless required by applicable law or agreed to in writing, software 111cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS, 121cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * See the License for the specific language governing permissions and 141cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato * limitations under the License. 151cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato */ 161cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 174528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tatepackage android.app.backup; 181cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 191cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onoratoimport java.io.FileDescriptor; 201cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onoratoimport java.io.IOException; 211cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 22e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate/** 234e14a829129feee14ebe453f61a124784c870610Christopher Tate * BackupDataInput is the structured interface used for passing the contents of 244e14a829129feee14ebe453f61a124784c870610Christopher Tate * a backup data set to an application's {@link BackupAgent} class in its 254e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor)} 264e14a829129feee14ebe453f61a124784c870610Christopher Tate * method. The data is presented as a set of "entities," each 274e14a829129feee14ebe453f61a124784c870610Christopher Tate * representing one named record as previously stored by the agent's 284e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link BackupAgent#onBackup(android.os.ParcelFileDescriptor, BackupDataOutput, android.os.ParcelFileDescriptor)} 294e14a829129feee14ebe453f61a124784c870610Christopher Tate * implementation. An entity is composed of a descriptive header plus a 304e14a829129feee14ebe453f61a124784c870610Christopher Tate * byte array that holds its raw data. 314e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p> 324e14a829129feee14ebe453f61a124784c870610Christopher Tate * The agent must consume every entity in the data stream, otherwise the 334e14a829129feee14ebe453f61a124784c870610Christopher Tate * restored state of the application will be incomplete. 344e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p> 354e14a829129feee14ebe453f61a124784c870610Christopher Tate * <b>Example</b> 364e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p> 374e14a829129feee14ebe453f61a124784c870610Christopher Tate * A typical 384e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) BackupAgent.onRestore(data, appVersionCode, newState)} 394e14a829129feee14ebe453f61a124784c870610Christopher Tate * implementation might be structured something like this: 404e14a829129feee14ebe453f61a124784c870610Christopher Tate * <pre> 414e14a829129feee14ebe453f61a124784c870610Christopher Tate * while (data.readNextHeader()) { 424e14a829129feee14ebe453f61a124784c870610Christopher Tate * String key = data.getKey(); 434e14a829129feee14ebe453f61a124784c870610Christopher Tate * int dataSize = data.getDataSize(); 444e14a829129feee14ebe453f61a124784c870610Christopher Tate * 454e14a829129feee14ebe453f61a124784c870610Christopher Tate * if (key.equals(MY_BACKUP_KEY_ONE)) { 464e14a829129feee14ebe453f61a124784c870610Christopher Tate * // process this kind of record here 474e14a829129feee14ebe453f61a124784c870610Christopher Tate * byte[] buffer = new byte[dataSize]; 484e14a829129feee14ebe453f61a124784c870610Christopher Tate * data.readEntityData(buffer, 0, dataSize); // reads the entire entity at once 494e14a829129feee14ebe453f61a124784c870610Christopher Tate * 504e14a829129feee14ebe453f61a124784c870610Christopher Tate * // now 'buffer' holds the raw data and can be processed however 514e14a829129feee14ebe453f61a124784c870610Christopher Tate * // the agent wishes 524e14a829129feee14ebe453f61a124784c870610Christopher Tate * processBackupKeyOne(buffer); 534e14a829129feee14ebe453f61a124784c870610Christopher Tate * } else if (key.equals(MY_BACKUP_KEY_TO_IGNORE) { 544e14a829129feee14ebe453f61a124784c870610Christopher Tate * // a key we recognize but wish to discard 554e14a829129feee14ebe453f61a124784c870610Christopher Tate * data.skipEntityData(); 564e14a829129feee14ebe453f61a124784c870610Christopher Tate * } // ... etc. 574e14a829129feee14ebe453f61a124784c870610Christopher Tate * }</pre> 58e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 591cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onoratopublic class BackupDataInput { 601cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato int mBackupReader; 611cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 621cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato private EntityHeader mHeader = new EntityHeader(); 631cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato private boolean mHeaderReady; 641cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 651cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato private static class EntityHeader { 661cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato String key; 671cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato int dataSize; 681cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 691cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 70e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** @hide */ 711cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato public BackupDataInput(FileDescriptor fd) { 721cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (fd == null) throw new NullPointerException(); 731cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato mBackupReader = ctor(fd); 741cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (mBackupReader == 0) { 751cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato throw new RuntimeException("Native initialization failed with fd=" + fd); 761cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 771cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 781cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 79e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** @hide */ 801cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato protected void finalize() throws Throwable { 811cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato try { 821cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato dtor(mBackupReader); 831cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } finally { 841cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato super.finalize(); 851cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 861cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 871cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 88e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** 894e14a829129feee14ebe453f61a124784c870610Christopher Tate * Extract the next entity header from the restore stream. After this method 904e14a829129feee14ebe453f61a124784c870610Christopher Tate * return success, the {@link #getKey()} and {@link #getDataSize()} methods can 914e14a829129feee14ebe453f61a124784c870610Christopher Tate * be used to inspect the entity that is now available for processing. 92e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * 934e14a829129feee14ebe453f61a124784c870610Christopher Tate * @return <code>true</code> when there is an entity ready for consumption from the 944e14a829129feee14ebe453f61a124784c870610Christopher Tate * restore stream, <code>false</code> if the restore stream has been fully consumed. 95e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @throws IOException if an error occurred while reading the restore stream 96e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 971cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato public boolean readNextHeader() throws IOException { 981cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato int result = readNextHeader_native(mBackupReader, mHeader); 991cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (result == 0) { 1001cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato // read successfully 1011cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato mHeaderReady = true; 1021cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato return true; 1031cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else if (result > 0) { 1041cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato // done 1051cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato mHeaderReady = false; 1061cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato return false; 1071cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else { 1081cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato // error 1091cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato mHeaderReady = false; 1104e14a829129feee14ebe453f61a124784c870610Christopher Tate throw new IOException("failed: 0x" + Integer.toHexString(result)); 1111cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1121cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1131cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 114e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** 1154e14a829129feee14ebe453f61a124784c870610Christopher Tate * Report the key associated with the current entity in the restore stream 1164e14a829129feee14ebe453f61a124784c870610Christopher Tate * @return the current entity's key string 117e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @throws IllegalStateException if the next record header has not yet been read 118e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 1191cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato public String getKey() { 1201cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (mHeaderReady) { 1211cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato return mHeader.key; 1221cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else { 1234e14a829129feee14ebe453f61a124784c870610Christopher Tate throw new IllegalStateException("Entity header not read"); 1241cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1251cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1261cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 127e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** 1284e14a829129feee14ebe453f61a124784c870610Christopher Tate * Report the size in bytes of the data associated with the current entity in the 129e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * restore stream. 130e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * 131e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @return The size of the record's raw data, in bytes 132e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @throws IllegalStateException if the next record header has not yet been read 133e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 1341cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato public int getDataSize() { 1351cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (mHeaderReady) { 1361cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato return mHeader.dataSize; 1371cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else { 1384e14a829129feee14ebe453f61a124784c870610Christopher Tate throw new IllegalStateException("Entity header not read"); 1391cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1401cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1411cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 142e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** 143e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * Read a record's raw data from the restore stream. The record's header must first 144e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * have been processed by the {@link #readNextHeader()} method. Multiple calls to 145e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * this method may be made in order to process the data in chunks; not all of it 1464e14a829129feee14ebe453f61a124784c870610Christopher Tate * must be read in a single call. Once all of the raw data for the current entity 1474e14a829129feee14ebe453f61a124784c870610Christopher Tate * has been read, further calls to this method will simply return zero. 148e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * 149e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @param data An allocated byte array of at least 'size' bytes 150e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @param offset Offset within the 'data' array at which the data will be placed 1514e14a829129feee14ebe453f61a124784c870610Christopher Tate * when read from the stream 1524e14a829129feee14ebe453f61a124784c870610Christopher Tate * @param size The number of bytes to read in this pass 1534e14a829129feee14ebe453f61a124784c870610Christopher Tate * @return The number of bytes of data read. Once all of the data for this entity 1544e14a829129feee14ebe453f61a124784c870610Christopher Tate * has been read, further calls to this method will return zero. 155e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @throws IOException if an error occurred when trying to read the restore data stream 156e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 1575f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato public int readEntityData(byte[] data, int offset, int size) throws IOException { 1581cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (mHeaderReady) { 1595f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato int result = readEntityData_native(mBackupReader, data, offset, size); 1601cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (result >= 0) { 1611cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato return result; 1621cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else { 1631cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato throw new IOException("result=0x" + Integer.toHexString(result)); 1641cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1651cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else { 1664e14a829129feee14ebe453f61a124784c870610Christopher Tate throw new IllegalStateException("Entity header not read"); 1671cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1681cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1691cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 170e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** 1714e14a829129feee14ebe453f61a124784c870610Christopher Tate * Consume the current entity's data without extracting it into a buffer 1724528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tate * for further processing. This allows a {@link android.app.backup.BackupAgent} to 173e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * efficiently discard obsolete or otherwise uninteresting records during the 174e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * restore operation. 175e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * 176e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @throws IOException if an error occurred when trying to read the restore data stream 177e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 1785f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato public void skipEntityData() throws IOException { 1795f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato if (mHeaderReady) { 1809bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato skipEntityData_native(mBackupReader); 1815f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato } else { 1824e14a829129feee14ebe453f61a124784c870610Christopher Tate throw new IllegalStateException("Entity header not read"); 1835f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato } 1845f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato } 1855f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato 1861cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato private native static int ctor(FileDescriptor fd); 1871cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato private native static void dtor(int mBackupReader); 1881cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 1891cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato private native int readNextHeader_native(int mBackupReader, EntityHeader entity); 1905f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato private native int readEntityData_native(int mBackupReader, byte[] data, int offset, int size); 1915f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato private native int skipEntityData_native(int mBackupReader); 1921cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato} 193