BackupDataOutput.java revision 4e14a829129feee14ebe453f61a124784c870610
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.app.backup; 18 19import android.os.ParcelFileDescriptor; 20 21import java.io.FileDescriptor; 22import java.io.IOException; 23 24/** 25 * This class is the structured conduit through which a {@link BackupAgent} commits 26 * information to the current backup data set. Data written for backup is presented 27 * as a set of "entities," key/value pairs in which each binary data record "value" is 28 * named with a string "key." 29 * <p> 30 * To commit a data record to the backup transport, the agent's 31 * {@link BackupAgent#onBackup(android.os.ParcelFileDescriptor, BackupDataOutput, android.os.ParcelFileDescriptor)} 32 * method first writes an "entity header" that supplies the key string for the record 33 * and the total size of the binary value for the record. After the header has been 34 * written the agent then writes the binary entity value itself. The entity value can 35 * be written in multiple chunks if desired, as long as the total count of bytes written 36 * matches what was supplied to {@link #writeEntityHeader(String, int)}. 37 * <p> 38 * Entity key strings are considered to be unique within a given application's backup 39 * data set. If a new entity is written under an existing key string, its value will 40 * replace any previous value in the transport's remote data store. A record can be 41 * removed entirely from the remote data set by writing a new entity header using the 42 * existing record's key, but supplying a negative <code>dataSize</code> parameter. 43 * When doing this the agent does not need to call {@link #writeEntityData(byte[], int)}. 44 * <p> 45 * <b>Example</b> 46 * <p> 47 * Here is an example illustrating a way to back up the value of a String variable 48 * called <code>mStringToBackUp</code>: 49 * <pre> 50 * static final String MY_STRING_KEY = "storedstring"; 51 * 52 * public void {@link BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)} 53 * throws IOException { 54 * ... 55 * byte[] stringBytes = mStringToBackUp.getBytes(); 56 * data.writeEntityHeader(MY_STRING_KEY, stringBytes.length); 57 * data.writeEntityData(stringBytes, stringBytes.length); 58 * ... 59 * }</pre> 60 * 61 * @see BackupAgent 62 */ 63public class BackupDataOutput { 64 int mBackupWriter; 65 66 /** @hide */ 67 public BackupDataOutput(FileDescriptor fd) { 68 if (fd == null) throw new NullPointerException(); 69 mBackupWriter = ctor(fd); 70 if (mBackupWriter == 0) { 71 throw new RuntimeException("Native initialization failed with fd=" + fd); 72 } 73 } 74 75 /** 76 * Mark the beginning of one record in the backup data stream. 77 * 78 * @param key 79 * @param dataSize The size in bytes of this record's data. Passing a dataSize 80 * of -1 indicates that the record under this key should be deleted. 81 * @return The number of bytes written to the backup stream 82 * @throws IOException if the write failed 83 */ 84 public int writeEntityHeader(String key, int dataSize) throws IOException { 85 int result = writeEntityHeader_native(mBackupWriter, key, dataSize); 86 if (result >= 0) { 87 return result; 88 } else { 89 throw new IOException("result=0x" + Integer.toHexString(result)); 90 } 91 } 92 93 /** 94 * Write a chunk of data under the current entity to the backup transport. 95 * @param data A raw data buffer to send 96 * @param size The number of bytes to be sent in this chunk 97 * @return the number of bytes written 98 * @throws IOException if the write failed 99 */ 100 public int writeEntityData(byte[] data, int size) throws IOException { 101 int result = writeEntityData_native(mBackupWriter, data, size); 102 if (result >= 0) { 103 return result; 104 } else { 105 throw new IOException("result=0x" + Integer.toHexString(result)); 106 } 107 } 108 109 /** @hide */ 110 public void setKeyPrefix(String keyPrefix) { 111 setKeyPrefix_native(mBackupWriter, keyPrefix); 112 } 113 114 /** @hide */ 115 protected void finalize() throws Throwable { 116 try { 117 dtor(mBackupWriter); 118 } finally { 119 super.finalize(); 120 } 121 } 122 123 private native static int ctor(FileDescriptor fd); 124 private native static void dtor(int mBackupWriter); 125 126 private native static int writeEntityHeader_native(int mBackupWriter, String key, int dataSize); 127 private native static int writeEntityData_native(int mBackupWriter, byte[] data, int size); 128 private native static void setKeyPrefix_native(int mBackupWriter, String keyPrefix); 129} 130 131