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
19ff31addb9b767496ba5c907513be172779eadfc5areteimport android.annotation.SystemApi;
204e14a829129feee14ebe453f61a124784c870610Christopher Tateimport android.os.ParcelFileDescriptor;
21b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratoimport java.io.FileDescriptor;
221cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onoratoimport java.io.IOException;
23b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato
24e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate/**
25d17da43c82c4edb97514d6138bc208eeba321636Scott Main * Provides the structured interface through which a {@link BackupAgent} commits
26d17da43c82c4edb97514d6138bc208eeba321636Scott Main * information to the backup data set, via its {@link
27d17da43c82c4edb97514d6138bc208eeba321636Scott Main * BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
28d17da43c82c4edb97514d6138bc208eeba321636Scott Main * onBackup()} method.  Data written for backup is presented
294e14a829129feee14ebe453f61a124784c870610Christopher Tate * as a set of "entities," key/value pairs in which each binary data record "value" is
304e14a829129feee14ebe453f61a124784c870610Christopher Tate * named with a string "key."
314e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
324e14a829129feee14ebe453f61a124784c870610Christopher Tate * To commit a data record to the backup transport, the agent's
33d17da43c82c4edb97514d6138bc208eeba321636Scott Main * {@link BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
34d17da43c82c4edb97514d6138bc208eeba321636Scott Main * onBackup()} method first writes an "entity header" that supplies the key string for the record
354e14a829129feee14ebe453f61a124784c870610Christopher Tate * and the total size of the binary value for the record.  After the header has been
36d17da43c82c4edb97514d6138bc208eeba321636Scott Main * written, the agent then writes the binary entity value itself.  The entity value can
374e14a829129feee14ebe453f61a124784c870610Christopher Tate * be written in multiple chunks if desired, as long as the total count of bytes written
38d17da43c82c4edb97514d6138bc208eeba321636Scott Main * matches what was supplied to {@link #writeEntityHeader(String, int) writeEntityHeader()}.
394e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
404e14a829129feee14ebe453f61a124784c870610Christopher Tate * Entity key strings are considered to be unique within a given application's backup
41d17da43c82c4edb97514d6138bc208eeba321636Scott Main * data set. If a backup agent writes a new entity under an existing key string, its value will
42d17da43c82c4edb97514d6138bc208eeba321636Scott Main * replace any previous value in the transport's remote data store.  You can remove a record
43d17da43c82c4edb97514d6138bc208eeba321636Scott Main * entirely from the remote data set by writing a new entity header using the
444e14a829129feee14ebe453f61a124784c870610Christopher Tate * existing record's key, but supplying a negative <code>dataSize</code> parameter.
45d17da43c82c4edb97514d6138bc208eeba321636Scott Main * When you do so, the agent does not need to call {@link #writeEntityData(byte[], int)}.
46d17da43c82c4edb97514d6138bc208eeba321636Scott Main * <h3>Example</h3>
474e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
484e14a829129feee14ebe453f61a124784c870610Christopher Tate * Here is an example illustrating a way to back up the value of a String variable
494e14a829129feee14ebe453f61a124784c870610Christopher Tate * called <code>mStringToBackUp</code>:
504e14a829129feee14ebe453f61a124784c870610Christopher Tate * <pre>
514e14a829129feee14ebe453f61a124784c870610Christopher Tate * static final String MY_STRING_KEY = "storedstring";
524e14a829129feee14ebe453f61a124784c870610Christopher Tate *
534e14a829129feee14ebe453f61a124784c870610Christopher Tate * public void {@link BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)}
544e14a829129feee14ebe453f61a124784c870610Christopher Tate *         throws IOException {
554e14a829129feee14ebe453f61a124784c870610Christopher Tate *     ...
564e14a829129feee14ebe453f61a124784c870610Christopher Tate *     byte[] stringBytes = mStringToBackUp.getBytes();
574e14a829129feee14ebe453f61a124784c870610Christopher Tate *     data.writeEntityHeader(MY_STRING_KEY, stringBytes.length);
584e14a829129feee14ebe453f61a124784c870610Christopher Tate *     data.writeEntityData(stringBytes, stringBytes.length);
594e14a829129feee14ebe453f61a124784c870610Christopher Tate *     ...
604e14a829129feee14ebe453f61a124784c870610Christopher Tate * }</pre>
614e14a829129feee14ebe453f61a124784c870610Christopher Tate *
624e14a829129feee14ebe453f61a124784c870610Christopher Tate * @see BackupAgent
63e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate */
64b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onoratopublic class BackupDataOutput {
65ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    final long mQuota;
6658b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat    long mBackupWriter;
67b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato
68ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    /**
69ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     * Construct a BackupDataOutput purely for data-stream manipulation.  This instance will
70ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     * not report usable quota information.
71ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     * @hide */
72ff31addb9b767496ba5c907513be172779eadfc5arete    @SystemApi
7383248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato    public BackupDataOutput(FileDescriptor fd) {
74ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate        this(fd, -1);
75ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    }
76ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate
77ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    /** @hide */
78ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    @SystemApi
79ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    public BackupDataOutput(FileDescriptor fd, long quota) {
80d2110dbce071a236b6176de344ca797b737542ebJoe Onorato        if (fd == null) throw new NullPointerException();
81ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate        mQuota = quota;
82d2110dbce071a236b6176de344ca797b737542ebJoe Onorato        mBackupWriter = ctor(fd);
83d2110dbce071a236b6176de344ca797b737542ebJoe Onorato        if (mBackupWriter == 0) {
84d2110dbce071a236b6176de344ca797b737542ebJoe Onorato            throw new RuntimeException("Native initialization failed with fd=" + fd);
85d2110dbce071a236b6176de344ca797b737542ebJoe Onorato        }
86b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato    }
87b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato
88e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate    /**
89ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     * Returns the quota in bytes for the application's current backup operation.  The
90ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     * value can vary for each operation.
91ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     *
92ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     * @see FullBackupDataOutput#getQuota()
93ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate     */
94ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    public long getQuota() {
95ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate        return mQuota;
96ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    }
97ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate
98ee87b96ee572e7245cf7b791e30c51505a8ba2a2Christopher Tate    /**
99d17da43c82c4edb97514d6138bc208eeba321636Scott Main     * Mark the beginning of one record in the backup data stream. This must be called before
100d17da43c82c4edb97514d6138bc208eeba321636Scott Main     * {@link #writeEntityData}.
101adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate     * @param key A string key that uniquely identifies the data record within the application.
102adfe8b86e9178a553b6db9722340fa4ff5201cf1Christopher Tate     *    Keys whose first character is \uFF00 or higher are not valid.
103e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * @param dataSize The size in bytes of this record's data.  Passing a dataSize
104e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     *    of -1 indicates that the record under this key should be deleted.
105e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * @return The number of bytes written to the backup stream
106e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * @throws IOException if the write failed
107e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     */
1081cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato    public int writeEntityHeader(String key, int dataSize) throws IOException {
1091cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato        int result = writeEntityHeader_native(mBackupWriter, key, dataSize);
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
117e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate    /**
118e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * Write a chunk of data under the current entity to the backup transport.
119e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * @param data A raw data buffer to send
120e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * @param size The number of bytes to be sent in this chunk
121e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * @return the number of bytes written
122e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     * @throws IOException if the write failed
123e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate     */
1241cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato    public int writeEntityData(byte[] data, int size) throws IOException {
1251cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato        int result = writeEntityData_native(mBackupWriter, data, size);
1261cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato        if (result >= 0) {
1271cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato            return result;
1281cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato        } else {
1291cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato            throw new IOException("result=0x" + Integer.toHexString(result));
1301cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato        }
1311cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato    }
1321cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato
133fc922f115325371aaadd4e423472476303039a72Christopher Tate    /** @hide */
13406290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    public void setKeyPrefix(String keyPrefix) {
13506290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato        setKeyPrefix_native(mBackupWriter, keyPrefix);
13606290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato    }
13706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
138e28290e21f908b4e917099ff2aa41e3aab9310c2Christopher Tate    /** @hide */
139ff31addb9b767496ba5c907513be172779eadfc5arete    @Override
140d2110dbce071a236b6176de344ca797b737542ebJoe Onorato    protected void finalize() throws Throwable {
141d2110dbce071a236b6176de344ca797b737542ebJoe Onorato        try {
142d2110dbce071a236b6176de344ca797b737542ebJoe Onorato            dtor(mBackupWriter);
143d2110dbce071a236b6176de344ca797b737542ebJoe Onorato        } finally {
144d2110dbce071a236b6176de344ca797b737542ebJoe Onorato            super.finalize();
145d2110dbce071a236b6176de344ca797b737542ebJoe Onorato        }
146b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato    }
14706290a4bb9b280fa14a2bbeb2d3ceb09396a78c3Joe Onorato
14858b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat    private native static long ctor(FileDescriptor fd);
14958b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat    private native static void dtor(long mBackupWriter);
1501cf587496fcb1d652bab9fc6792fb106b6fefaa4Joe Onorato
15158b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat    private native static int writeEntityHeader_native(long mBackupWriter, String key, int dataSize);
15258b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat    private native static int writeEntityData_native(long mBackupWriter, byte[] data, int size);
15358b8b24256bdc2b613b7fda9151845ed9898a4c7Ashok Bhat    private native static void setKeyPrefix_native(long mBackupWriter, String keyPrefix);
154b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato}
155b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato
156