1487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate/*
2487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * Copyright (C) 2009 The Android Open Source Project
3487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate *
4487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * Licensed under the Apache License, Version 2.0 (the "License");
5487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * you may not use this file except in compliance with the License.
6487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * You may obtain a copy of the License at
7487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate *
8487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate *      http://www.apache.org/licenses/LICENSE-2.0
9487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate *
10487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * Unless required by applicable law or agreed to in writing, software
11487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * distributed under the License is distributed on an "AS IS" BASIS,
12487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * See the License for the specific language governing permissions and
14487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate * limitations under the License.
15487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate */
16487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
174528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tatepackage android.app.backup;
18487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
19181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tateimport android.app.IBackupAgent;
204528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tateimport android.app.backup.IBackupManager;
21181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tateimport android.content.Context;
22181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tateimport android.content.ContextWrapper;
231902492420825874b12962a10712e653901d120dChristopher Tateimport android.os.Binder;
24487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tateimport android.os.IBinder;
2522b8787ed4be8d4b7ed5d54802f9913fedb41425Christopher Tateimport android.os.ParcelFileDescriptor;
26487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tateimport android.os.RemoteException;
27487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tateimport android.util.Log;
28487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
2983248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onoratoimport java.io.IOException;
3083248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato
31487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate/**
32d17da43c82c4edb97514d6138bc208eeba321636Scott Main * Provides the central interface between an
334e14a829129feee14ebe453f61a124784c870610Christopher Tate * application and Android's data backup infrastructure.  An application that wishes
344e14a829129feee14ebe453f61a124784c870610Christopher Tate * to participate in the backup and restore mechanism will declare a subclass of
354e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link android.app.backup.BackupAgent}, implement the
36d17da43c82c4edb97514d6138bc208eeba321636Scott Main * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup()}
37d17da43c82c4edb97514d6138bc208eeba321636Scott Main * and {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor) onRestore()} methods,
38d17da43c82c4edb97514d6138bc208eeba321636Scott Main * and provide the name of its backup agent class in its {@code AndroidManifest.xml} file via
39d17da43c82c4edb97514d6138bc208eeba321636Scott Main * the <code><a
40d17da43c82c4edb97514d6138bc208eeba321636Scott Main * href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
41d17da43c82c4edb97514d6138bc208eeba321636Scott Main * tag's {@code android:backupAgent} attribute.
42d17da43c82c4edb97514d6138bc208eeba321636Scott Main * <h3>Basic Operation</h3>
435a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root * <p>
444e14a829129feee14ebe453f61a124784c870610Christopher Tate * When the application makes changes to data that it wishes to keep backed up,
454e14a829129feee14ebe453f61a124784c870610Christopher Tate * it should call the
464e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link android.app.backup.BackupManager#dataChanged() BackupManager.dataChanged()} method.
47d17da43c82c4edb97514d6138bc208eeba321636Scott Main * This notifies the Android Backup Manager that the application needs an opportunity
48d17da43c82c4edb97514d6138bc208eeba321636Scott Main * to update its backup image.  The Backup Manager, in turn, schedules a
494e14a829129feee14ebe453f61a124784c870610Christopher Tate * backup pass to be performed at an opportune time.
504e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
51d17da43c82c4edb97514d6138bc208eeba321636Scott Main * Restore operations are typically performed only when applications are first
524e14a829129feee14ebe453f61a124784c870610Christopher Tate * installed on a device.  At that time, the operating system checks to see whether
53d17da43c82c4edb97514d6138bc208eeba321636Scott Main * there is a previously-saved data set available for the application being installed, and if so,
54d17da43c82c4edb97514d6138bc208eeba321636Scott Main * begins an immediate restore pass to deliver the backup data as part of the installation
554e14a829129feee14ebe453f61a124784c870610Christopher Tate * process.
564e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
57d17da43c82c4edb97514d6138bc208eeba321636Scott Main * When a backup or restore pass is run, the application's process is launched
58d17da43c82c4edb97514d6138bc208eeba321636Scott Main * (if not already running), the manifest-declared backup agent class (in the {@code
59d17da43c82c4edb97514d6138bc208eeba321636Scott Main * android:backupAgent} attribute) is instantiated within
60d17da43c82c4edb97514d6138bc208eeba321636Scott Main * that process, and the agent's {@link #onCreate()} method is invoked.  This prepares the
614e14a829129feee14ebe453f61a124784c870610Christopher Tate * agent instance to run the actual backup or restore logic.  At this point the
624e14a829129feee14ebe453f61a124784c870610Christopher Tate * agent's
634e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup()} or
644e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor) onRestore()} method will be
654e14a829129feee14ebe453f61a124784c870610Christopher Tate * invoked as appropriate for the operation being performed.
664e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
67d17da43c82c4edb97514d6138bc208eeba321636Scott Main * A backup data set consists of one or more "entities," flattened binary data
68d17da43c82c4edb97514d6138bc208eeba321636Scott Main * records that are each identified with a key string unique within the data set.  Adding a
69d17da43c82c4edb97514d6138bc208eeba321636Scott Main * record to the active data set or updating an existing record is done by simply
704e14a829129feee14ebe453f61a124784c870610Christopher Tate * writing new entity data under the desired key.  Deleting an entity from the data set
714e14a829129feee14ebe453f61a124784c870610Christopher Tate * is done by writing an entity under that key with header specifying a negative data
724e14a829129feee14ebe453f61a124784c870610Christopher Tate * size, and no actual entity data.
734e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
744e14a829129feee14ebe453f61a124784c870610Christopher Tate * <b>Helper Classes</b>
754e14a829129feee14ebe453f61a124784c870610Christopher Tate * <p>
764e14a829129feee14ebe453f61a124784c870610Christopher Tate * An extensible agent based on convenient helper classes is available in
774e14a829129feee14ebe453f61a124784c870610Christopher Tate * {@link android.app.backup.BackupAgentHelper}.  That class is particularly
784e14a829129feee14ebe453f61a124784c870610Christopher Tate * suited to handling of simple file or {@link android.content.SharedPreferences}
794e14a829129feee14ebe453f61a124784c870610Christopher Tate * backup and restore.
804e14a829129feee14ebe453f61a124784c870610Christopher Tate *
814e14a829129feee14ebe453f61a124784c870610Christopher Tate * @see android.app.backup.BackupManager
824e14a829129feee14ebe453f61a124784c870610Christopher Tate * @see android.app.backup.BackupAgentHelper
834e14a829129feee14ebe453f61a124784c870610Christopher Tate * @see android.app.backup.BackupDataInput
844e14a829129feee14ebe453f61a124784c870610Christopher Tate * @see android.app.backup.BackupDataOutput
85487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate */
86181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tatepublic abstract class BackupAgent extends ContextWrapper {
8783248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato    private static final String TAG = "BackupAgent";
88436344ae12c819f58306ceb94241a266141e1218Christopher Tate    private static final boolean DEBUG = false;
8983248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato
90181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    public BackupAgent() {
91181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate        super(null);
92181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    }
93487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
944e14a829129feee14ebe453f61a124784c870610Christopher Tate    /**
954e14a829129feee14ebe453f61a124784c870610Christopher Tate     * Provided as a convenience for agent implementations that need an opportunity
964e14a829129feee14ebe453f61a124784c870610Christopher Tate     * to do one-time initialization before the actual backup or restore operation
974e14a829129feee14ebe453f61a124784c870610Christopher Tate     * is begun.
984e14a829129feee14ebe453f61a124784c870610Christopher Tate     * <p>
994e14a829129feee14ebe453f61a124784c870610Christopher Tate     * Agents do not need to override this method.
1004e14a829129feee14ebe453f61a124784c870610Christopher Tate     */
101181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    public void onCreate() {
102181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    }
103181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate
1044e14a829129feee14ebe453f61a124784c870610Christopher Tate    /**
1054e14a829129feee14ebe453f61a124784c870610Christopher Tate     * Provided as a convenience for agent implementations that need to do some
1064e14a829129feee14ebe453f61a124784c870610Christopher Tate     * sort of shutdown process after backup or restore is completed.
1074e14a829129feee14ebe453f61a124784c870610Christopher Tate     * <p>
1084e14a829129feee14ebe453f61a124784c870610Christopher Tate     * Agents do not need to override this method.
1094e14a829129feee14ebe453f61a124784c870610Christopher Tate     */
110181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    public void onDestroy() {
111181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    }
112487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
113487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate    /**
1145a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * The application is being asked to write any data changed since the last
1155a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * time it performed a backup operation. The state data recorded during the
1165a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * last backup pass is provided in the <code>oldState</code> file
1175a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * descriptor. If <code>oldState</code> is <code>null</code>, no old state
1185a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * is available and the application should perform a full backup. In both
1195a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * cases, a representation of the final backup state after this pass should
1205a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * be written to the file pointed to by the file descriptor wrapped in
1215a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * <code>newState</code>.
1224e14a829129feee14ebe453f61a124784c870610Christopher Tate     * <p>
1234e14a829129feee14ebe453f61a124784c870610Christopher Tate     * Each entity written to the {@link android.app.backup.BackupDataOutput}
1244e14a829129feee14ebe453f61a124784c870610Christopher Tate     * <code>data</code> stream will be transmitted
1254e14a829129feee14ebe453f61a124784c870610Christopher Tate     * over the current backup transport and stored in the remote data set under
1264e14a829129feee14ebe453f61a124784c870610Christopher Tate     * the key supplied as part of the entity.  Writing an entity with a negative
1274e14a829129feee14ebe453f61a124784c870610Christopher Tate     * data size instructs the transport to delete whatever entity currently exists
1284e14a829129feee14ebe453f61a124784c870610Christopher Tate     * under that key from the remote data set.
1295a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *
1305a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * @param oldState An open, read-only ParcelFileDescriptor pointing to the
1315a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            last backup state provided by the application. May be
1325a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            <code>null</code>, in which case no prior state is being
1335a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            provided and the application should perform a full backup.
1345a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * @param data A structured wrapper around an open, read/write
1354e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            file descriptor pointing to the backup data destination.
1365a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            Typically the application will use backup helper classes to
1375a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            write to this file.
1385a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * @param newState An open, read/write ParcelFileDescriptor pointing to an
1395a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            empty file. The application should record the final backup
1404e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            state here after writing the requested data to the <code>data</code>
1414e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            output stream.
142487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate     */
143290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato    public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
1444ababd922eac5931e0222862ff082dc29e012816Joe Onorato             ParcelFileDescriptor newState) throws IOException;
1455a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root
146487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate    /**
1475a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * The application is being restored from backup and should replace any
1485a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * existing data with the contents of the backup. The backup data is
1494e14a829129feee14ebe453f61a124784c870610Christopher Tate     * provided through the <code>data</code> parameter. Once
1505a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * the restore is finished, the application should write a representation of
1515a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * the final state to the <code>newState</code> file descriptor.
1525a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * <p>
1535a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * The application is responsible for properly erasing its old data and
1545a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * replacing it with the data supplied to this method. No "clear user data"
1555a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * operation will be performed automatically by the operating system. The
1565a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * exception to this is in the case of a failed restore attempt: if
1575a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * onRestore() throws an exception, the OS will assume that the
1585a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * application's data may now be in an incoherent state, and will clear it
1595a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * before proceeding.
1605a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *
1615a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * @param data A structured wrapper around an open, read-only
1624e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            file descriptor pointing to a full snapshot of the
1634e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            application's data.  The application should consume every
1644e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            entity represented in this data stream.
165b83a283ac178ab0a72f1d811189d79b26097835eScott Main     * @param appVersionCode The value of the <a
166b83a283ac178ab0a72f1d811189d79b26097835eScott Main     * href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
167b83a283ac178ab0a72f1d811189d79b26097835eScott Main     *            android:versionCode}</a> manifest attribute,
168b83a283ac178ab0a72f1d811189d79b26097835eScott Main     *            from the application that backed up this particular data set. This
1694e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            makes it possible for an application's agent to distinguish among any
1705a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            possible older data versions when asked to perform the restore
1715a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            operation.
1725a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     * @param newState An open, read/write ParcelFileDescriptor pointing to an
1735a20ea16d7e5b70dc7bad8700f54170e4f220d12Kenny Root     *            empty file. The application should record the final backup
1744e14a829129feee14ebe453f61a124784c870610Christopher Tate     *            state here after restoring its data from the <code>data</code> stream.
175487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate     */
1765cbbf5652a78902ac3382dc4a3583bc5b0351027Christopher Tate    public abstract void onRestore(BackupDataInput data, int appVersionCode,
1775cbbf5652a78902ac3382dc4a3583bc5b0351027Christopher Tate            ParcelFileDescriptor newState)
17883248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato            throws IOException;
179487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
180487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
181487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate    // ----- Core implementation -----
18244a2790374bf27116cbd91060d4f096ca5999709Christopher Tate
18344a2790374bf27116cbd91060d4f096ca5999709Christopher Tate    /** @hide */
18444a2790374bf27116cbd91060d4f096ca5999709Christopher Tate    public final IBinder onBind() {
185181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate        return mBinder;
186487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate    }
187487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
188487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate    private final IBinder mBinder = new BackupServiceBinder().asBinder();
189487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
190181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    /** @hide */
191181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    public void attach(Context context) {
192181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate        attachBaseContext(context);
193181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    }
194181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate
195487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate    // ----- IBackupService binder interface -----
196181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate    private class BackupServiceBinder extends IBackupAgent.Stub {
197181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate        private static final String TAG = "BackupServiceBinder";
198181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate
19922b8787ed4be8d4b7ed5d54802f9913fedb41425Christopher Tate        public void doBackup(ParcelFileDescriptor oldState,
20022b8787ed4be8d4b7ed5d54802f9913fedb41425Christopher Tate                ParcelFileDescriptor data,
20144a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                ParcelFileDescriptor newState,
20244a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                int token, IBackupManager callbackBinder) throws RemoteException {
2031902492420825874b12962a10712e653901d120dChristopher Tate            // Ensure that we're running with the app's normal permission level
20444a2790374bf27116cbd91060d4f096ca5999709Christopher Tate            long ident = Binder.clearCallingIdentity();
2051902492420825874b12962a10712e653901d120dChristopher Tate
206436344ae12c819f58306ceb94241a266141e1218Christopher Tate            if (DEBUG) Log.v(TAG, "doBackup() invoked");
20783248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato            BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
208290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato            try {
209181fafaf48208978b8ba2022683ffa78aaeddde1Christopher Tate                BackupAgent.this.onBackup(oldState, output, newState);
2104ababd922eac5931e0222862ff082dc29e012816Joe Onorato            } catch (IOException ex) {
2114ababd922eac5931e0222862ff082dc29e012816Joe Onorato                Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
2124ababd922eac5931e0222862ff082dc29e012816Joe Onorato                throw new RuntimeException(ex);
213290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato            } catch (RuntimeException ex) {
21483248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato                Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
215290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato                throw ex;
2161902492420825874b12962a10712e653901d120dChristopher Tate            } finally {
21744a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                Binder.restoreCallingIdentity(ident);
21844a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                try {
21944a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                    callbackBinder.opComplete(token);
22044a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                } catch (RemoteException e) {
22144a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                    // we'll time out anyway, so we're safe
22244a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                }
223290bb011c5c1a9ba1f2116810b06cf52a9c36b3eJoe Onorato            }
224487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate        }
225487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate
2265cbbf5652a78902ac3382dc4a3583bc5b0351027Christopher Tate        public void doRestore(ParcelFileDescriptor data, int appVersionCode,
22744a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                ParcelFileDescriptor newState,
22844a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                int token, IBackupManager callbackBinder) throws RemoteException {
2291902492420825874b12962a10712e653901d120dChristopher Tate            // Ensure that we're running with the app's normal permission level
23044a2790374bf27116cbd91060d4f096ca5999709Christopher Tate            long ident = Binder.clearCallingIdentity();
2311902492420825874b12962a10712e653901d120dChristopher Tate
232436344ae12c819f58306ceb94241a266141e1218Christopher Tate            if (DEBUG) Log.v(TAG, "doRestore() invoked");
23383248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato            BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
23483248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato            try {
2355cbbf5652a78902ac3382dc4a3583bc5b0351027Christopher Tate                BackupAgent.this.onRestore(input, appVersionCode, newState);
23683248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato            } catch (IOException ex) {
23783248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato                Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
23883248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato                throw new RuntimeException(ex);
23983248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato            } catch (RuntimeException ex) {
24083248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato                Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
24183248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato                throw ex;
2421902492420825874b12962a10712e653901d120dChristopher Tate            } finally {
24344a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                Binder.restoreCallingIdentity(ident);
24444a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                try {
24544a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                    callbackBinder.opComplete(token);
24644a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                } catch (RemoteException e) {
24744a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                    // we'll time out anyway, so we're safe
24844a2790374bf27116cbd91060d4f096ca5999709Christopher Tate                }
24983248c432ffe2e2a17abbc8e4960c26574b46bcaJoe Onorato            }
250487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate        }
251487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate    }
252487529a70cd1479ae8d6bbfb356be7e72542c185Christopher Tate}
253