BackupDataInput.java revision 4528186e0d65fc68ef0dd1941aa2ac8aefcd55a3
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 java.io.FileDescriptor;
20import java.io.IOException;
21
22/**
23 * STOPSHIP: document!
24 */
25public class BackupDataInput {
26    int mBackupReader;
27
28    private EntityHeader mHeader = new EntityHeader();
29    private boolean mHeaderReady;
30
31    private static class EntityHeader {
32        String key;
33        int dataSize;
34    }
35
36    /** @hide */
37    public BackupDataInput(FileDescriptor fd) {
38        if (fd == null) throw new NullPointerException();
39        mBackupReader = ctor(fd);
40        if (mBackupReader == 0) {
41            throw new RuntimeException("Native initialization failed with fd=" + fd);
42        }
43    }
44
45    /** @hide */
46    protected void finalize() throws Throwable {
47        try {
48            dtor(mBackupReader);
49        } finally {
50            super.finalize();
51        }
52    }
53
54    /**
55     * Consumes the next header from the restore stream.
56     *
57     * @return true when there is an entity ready for consumption from the restore stream,
58     *    false if the restore stream has been fully consumed.
59     * @throws IOException if an error occurred while reading the restore stream
60     */
61    public boolean readNextHeader() throws IOException {
62        int result = readNextHeader_native(mBackupReader, mHeader);
63        if (result == 0) {
64            // read successfully
65            mHeaderReady = true;
66            return true;
67        } else if (result > 0) {
68            // done
69            mHeaderReady = false;
70            return false;
71        } else {
72            // error
73            mHeaderReady = false;
74            throw new IOException("result=0x" + Integer.toHexString(result));
75        }
76    }
77
78    /**
79     * Report the key associated with the current record in the restore stream
80     * @return the current record's key string
81     * @throws IllegalStateException if the next record header has not yet been read
82     */
83    public String getKey() {
84        if (mHeaderReady) {
85            return mHeader.key;
86        } else {
87            throw new IllegalStateException("mHeaderReady=false");
88        }
89    }
90
91    /**
92     * Report the size in bytes of the data associated with the current record in the
93     * restore stream.
94     *
95     * @return The size of the record's raw data, in bytes
96     * @throws IllegalStateException if the next record header has not yet been read
97     */
98    public int getDataSize() {
99        if (mHeaderReady) {
100            return mHeader.dataSize;
101        } else {
102            throw new IllegalStateException("mHeaderReady=false");
103        }
104    }
105
106    /**
107     * Read a record's raw data from the restore stream.  The record's header must first
108     * have been processed by the {@link #readNextHeader()} method.  Multiple calls to
109     * this method may be made in order to process the data in chunks; not all of it
110     * must be read in a single call.
111     *
112     * @param data An allocated byte array of at least 'size' bytes
113     * @param offset Offset within the 'data' array at which the data will be placed
114     *    when read from the stream.
115     * @param size The number of bytes to read in this pass.
116     * @return The number of bytes of data read
117     * @throws IOException if an error occurred when trying to read the restore data stream
118     */
119    public int readEntityData(byte[] data, int offset, int size) throws IOException {
120        if (mHeaderReady) {
121            int result = readEntityData_native(mBackupReader, data, offset, size);
122            if (result >= 0) {
123                return result;
124            } else {
125                throw new IOException("result=0x" + Integer.toHexString(result));
126            }
127        } else {
128            throw new IllegalStateException("mHeaderReady=false");
129        }
130    }
131
132    /**
133     * Consume the current record's data without actually reading it into a buffer
134     * for further processing.  This allows a {@link android.app.backup.BackupAgent} to
135     * efficiently discard obsolete or otherwise uninteresting records during the
136     * restore operation.
137     *
138     * @throws IOException if an error occurred when trying to read the restore data stream
139     */
140    public void skipEntityData() throws IOException {
141        if (mHeaderReady) {
142            skipEntityData_native(mBackupReader);
143        } else {
144            throw new IllegalStateException("mHeaderReady=false");
145        }
146    }
147
148    private native static int ctor(FileDescriptor fd);
149    private native static void dtor(int mBackupReader);
150
151    private native int readNextHeader_native(int mBackupReader, EntityHeader entity);
152    private native int readEntityData_native(int mBackupReader, byte[] data, int offset, int size);
153    private native int skipEntityData_native(int mBackupReader);
154}
155