blob: 2da0c11182b87a630300ebe20d97800634456565 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.backup;
import java.io.FileDescriptor;
import java.io.IOException;
/**
* STOPSHIP: document!
*/
public class BackupDataInput {
int mBackupReader;
private EntityHeader mHeader = new EntityHeader();
private boolean mHeaderReady;
private static class EntityHeader {
String key;
int dataSize;
}
/** @hide */
public BackupDataInput(FileDescriptor fd) {
if (fd == null) throw new NullPointerException();
mBackupReader = ctor(fd);
if (mBackupReader == 0) {
throw new RuntimeException("Native initialization failed with fd=" + fd);
}
}
/** @hide */
protected void finalize() throws Throwable {
try {
dtor(mBackupReader);
} finally {
super.finalize();
}
}
/**
* Consumes the next header from the restore stream.
*
* @return true when there is an entity ready for consumption from the restore stream,
* false if the restore stream has been fully consumed.
* @throws IOException if an error occurred while reading the restore stream
*/
public boolean readNextHeader() throws IOException {
int result = readNextHeader_native(mBackupReader, mHeader);
if (result == 0) {
// read successfully
mHeaderReady = true;
return true;
} else if (result > 0) {
// done
mHeaderReady = false;
return false;
} else {
// error
mHeaderReady = false;
throw new IOException("result=0x" + Integer.toHexString(result));
}
}
/**
* Report the key associated with the current record in the restore stream
* @return the current record's key string
* @throws IllegalStateException if the next record header has not yet been read
*/
public String getKey() {
if (mHeaderReady) {
return mHeader.key;
} else {
throw new IllegalStateException("mHeaderReady=false");
}
}
/**
* Report the size in bytes of the data associated with the current record in the
* restore stream.
*
* @return The size of the record's raw data, in bytes
* @throws IllegalStateException if the next record header has not yet been read
*/
public int getDataSize() {
if (mHeaderReady) {
return mHeader.dataSize;
} else {
throw new IllegalStateException("mHeaderReady=false");
}
}
/**
* Read a record's raw data from the restore stream. The record's header must first
* have been processed by the {@link #readNextHeader()} method. Multiple calls to
* this method may be made in order to process the data in chunks; not all of it
* must be read in a single call.
*
* @param data An allocated byte array of at least 'size' bytes
* @param offset Offset within the 'data' array at which the data will be placed
* when read from the stream.
* @param size The number of bytes to read in this pass.
* @return The number of bytes of data read
* @throws IOException if an error occurred when trying to read the restore data stream
*/
public int readEntityData(byte[] data, int offset, int size) throws IOException {
if (mHeaderReady) {
int result = readEntityData_native(mBackupReader, data, offset, size);
if (result >= 0) {
return result;
} else {
throw new IOException("result=0x" + Integer.toHexString(result));
}
} else {
throw new IllegalStateException("mHeaderReady=false");
}
}
/**
* Consume the current record's data without actually reading it into a buffer
* for further processing. This allows a {@link android.app.backup.BackupAgent} to
* efficiently discard obsolete or otherwise uninteresting records during the
* restore operation.
*
* @throws IOException if an error occurred when trying to read the restore data stream
*/
public void skipEntityData() throws IOException {
if (mHeaderReady) {
skipEntityData_native(mBackupReader);
} else {
throw new IllegalStateException("mHeaderReady=false");
}
}
private native static int ctor(FileDescriptor fd);
private native static void dtor(int mBackupReader);
private native int readNextHeader_native(int mBackupReader, EntityHeader entity);
private native int readEntityData_native(int mBackupReader, byte[] data, int offset, int size);
private native int skipEntityData_native(int mBackupReader);
}