BackupDataOutput.java revision adfe8b86e9178a553b6db9722340fa4ff5201cf1
1b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato/* 2b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Copyright (C) 2009 The Android Open Source Project 3b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 4b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License"); 5b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * you may not use this file except in compliance with the License. 6b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * You may obtain a copy of the License at 7b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 8b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * http://www.apache.org/licenses/LICENSE-2.0 9b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 10b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Unless required by applicable law or agreed to in writing, software 11b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS, 12b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * See the License for the specific language governing permissions and 14b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * limitations under the License. 15b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato */ 16b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 174528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tatepackage android.app.backup; 18b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 194e14a829129feee14ebe453f61a124784c870610Christopher Tateimport android.os.ParcelFileDescriptor; 20adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tateimport android.os.Process; 214e14a829129feee14ebe453f61a124784c870610Christopher Tate 22b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.io.FileDescriptor; 231cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onoratoimport java.io.IOException; 24b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 25e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate/** 26d17da43c82c4edb97514d6138bc208eeba321636Scott Main * Provides the structured interface through which a {@link BackupAgent} commits 27d17da43c82c4edb97514d6138bc208eeba321636Scott Main * information to the backup data set, via its {@link 28d17da43c82c4edb97514d6138bc208eeba321636Scott Main * BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) 29d17da43c82c4edb97514d6138bc208eeba321636Scott Main * onBackup()} method. Data written for backup is presented 304e14a829129feee14ebe453f61a124784c870610Christopher Tate * as a set of "entities," key/value pairs in which each binary data record "value" is 314e14a829129feee14ebe453f61a124784c870610Christopher Tate * named with a string "key." 324e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p> 334e14a829129feee14ebe453f61a124784c870610Christopher Tate * To commit a data record to the backup transport, the agent's 34d17da43c82c4edb97514d6138bc208eeba321636Scott Main * {@link BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) 35d17da43c82c4edb97514d6138bc208eeba321636Scott Main * onBackup()} method first writes an "entity header" that supplies the key string for the record 364e14a829129feee14ebe453f61a124784c870610Christopher Tate * and the total size of the binary value for the record. After the header has been 37d17da43c82c4edb97514d6138bc208eeba321636Scott Main * written, the agent then writes the binary entity value itself. The entity value can 384e14a829129feee14ebe453f61a124784c870610Christopher Tate * be written in multiple chunks if desired, as long as the total count of bytes written 39d17da43c82c4edb97514d6138bc208eeba321636Scott Main * matches what was supplied to {@link #writeEntityHeader(String, int) writeEntityHeader()}. 404e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p> 414e14a829129feee14ebe453f61a124784c870610Christopher Tate * Entity key strings are considered to be unique within a given application's backup 42d17da43c82c4edb97514d6138bc208eeba321636Scott Main * data set. If a backup agent writes a new entity under an existing key string, its value will 43d17da43c82c4edb97514d6138bc208eeba321636Scott Main * replace any previous value in the transport's remote data store. You can remove a record 44d17da43c82c4edb97514d6138bc208eeba321636Scott Main * entirely from the remote data set by writing a new entity header using the 454e14a829129feee14ebe453f61a124784c870610Christopher Tate * existing record's key, but supplying a negative <code>dataSize</code> parameter. 46d17da43c82c4edb97514d6138bc208eeba321636Scott Main * When you do so, the agent does not need to call {@link #writeEntityData(byte[], int)}. 47d17da43c82c4edb97514d6138bc208eeba321636Scott Main * <h3>Example</h3> 484e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p> 494e14a829129feee14ebe453f61a124784c870610Christopher Tate * Here is an example illustrating a way to back up the value of a String variable 504e14a829129feee14ebe453f61a124784c870610Christopher Tate * called <code>mStringToBackUp</code>: 514e14a829129feee14ebe453f61a124784c870610Christopher Tate * <pre> 524e14a829129feee14ebe453f61a124784c870610Christopher Tate * static final String MY_STRING_KEY = "storedstring"; 534e14a829129feee14ebe453f61a124784c870610Christopher Tate * 544e14a829129feee14ebe453f61a124784c870610Christopher Tate * public void {@link BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)} 554e14a829129feee14ebe453f61a124784c870610Christopher Tate * throws IOException { 564e14a829129feee14ebe453f61a124784c870610Christopher Tate * ... 574e14a829129feee14ebe453f61a124784c870610Christopher Tate * byte[] stringBytes = mStringToBackUp.getBytes(); 584e14a829129feee14ebe453f61a124784c870610Christopher Tate * data.writeEntityHeader(MY_STRING_KEY, stringBytes.length); 594e14a829129feee14ebe453f61a124784c870610Christopher Tate * data.writeEntityData(stringBytes, stringBytes.length); 604e14a829129feee14ebe453f61a124784c870610Christopher Tate * ... 614e14a829129feee14ebe453f61a124784c870610Christopher Tate * }</pre> 624e14a829129feee14ebe453f61a124784c870610Christopher Tate * 634e14a829129feee14ebe453f61a124784c870610Christopher Tate * @see BackupAgent 64e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 65b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratopublic class BackupDataOutput { 6658b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat long mBackupWriter; 67b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 68e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** @hide */ 6983248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato public BackupDataOutput(FileDescriptor fd) { 70d2110dbce071a236b6176de344ca797b737542ebJoe Onorato if (fd == null) throw new NullPointerException(); 71d2110dbce071a236b6176de344ca797b737542ebJoe Onorato mBackupWriter = ctor(fd); 72d2110dbce071a236b6176de344ca797b737542ebJoe Onorato if (mBackupWriter == 0) { 73d2110dbce071a236b6176de344ca797b737542ebJoe Onorato throw new RuntimeException("Native initialization failed with fd=" + fd); 74d2110dbce071a236b6176de344ca797b737542ebJoe Onorato } 75b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato } 76b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 77e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** 78d17da43c82c4edb97514d6138bc208eeba321636Scott Main * Mark the beginning of one record in the backup data stream. This must be called before 79d17da43c82c4edb97514d6138bc208eeba321636Scott Main * {@link #writeEntityData}. 80adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate * @param key A string key that uniquely identifies the data record within the application. 81adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate * Keys whose first character is \uFF00 or higher are not valid. 82e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @param dataSize The size in bytes of this record's data. Passing a dataSize 83e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * of -1 indicates that the record under this key should be deleted. 84e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @return The number of bytes written to the backup stream 85e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @throws IOException if the write failed 86e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 871cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato public int writeEntityHeader(String key, int dataSize) throws IOException { 88adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate if (key != null && key.charAt(0) >= 0xff00) { 89adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate if (Process.myUid() != Process.SYSTEM_UID) { 90adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate throw new IllegalArgumentException("Invalid key " + key); 91adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 92adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate } 931cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato int result = writeEntityHeader_native(mBackupWriter, key, dataSize); 941cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (result >= 0) { 951cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato return result; 961cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else { 971cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato throw new IOException("result=0x" + Integer.toHexString(result)); 981cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 991cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1001cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 101e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** 102e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * Write a chunk of data under the current entity to the backup transport. 103e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @param data A raw data buffer to send 104e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @param size The number of bytes to be sent in this chunk 105e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @return the number of bytes written 106e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate * @throws IOException if the write failed 107e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */ 1081cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato public int writeEntityData(byte[] data, int size) throws IOException { 1091cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato int result = writeEntityData_native(mBackupWriter, data, size); 1101cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato if (result >= 0) { 1111cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato return result; 1121cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } else { 1131cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato throw new IOException("result=0x" + Integer.toHexString(result)); 1141cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1151cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato } 1161cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 117fc922f115325371aaadd4e423472476303039a72Christopher Tate /** @hide */ 11806290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato public void setKeyPrefix(String keyPrefix) { 11906290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato setKeyPrefix_native(mBackupWriter, keyPrefix); 12006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato } 12106290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato 122e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate /** @hide */ 123d2110dbce071a236b6176de344ca797b737542ebJoe Onorato protected void finalize() throws Throwable { 124d2110dbce071a236b6176de344ca797b737542ebJoe Onorato try { 125d2110dbce071a236b6176de344ca797b737542ebJoe Onorato dtor(mBackupWriter); 126d2110dbce071a236b6176de344ca797b737542ebJoe Onorato } finally { 127d2110dbce071a236b6176de344ca797b737542ebJoe Onorato super.finalize(); 128d2110dbce071a236b6176de344ca797b737542ebJoe Onorato } 129b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato } 13006290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato 13158b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat private native static long ctor(FileDescriptor fd); 13258b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat private native static void dtor(long mBackupWriter); 1331cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato 13458b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat private native static int writeEntityHeader_native(long mBackupWriter, String key, int dataSize); 13558b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat private native static int writeEntityData_native(long mBackupWriter, byte[] data, int size); 13658b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat private native static void setKeyPrefix_native(long mBackupWriter, String keyPrefix); 137b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato} 138b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato 139