Trampoline.java revision 511d02fcc37dce092e17354d53023db44817ebe6
1/*
2 * Copyright (C) 2014 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 com.android.server.backup;
18
19import android.app.backup.IBackupManager;
20import android.app.backup.IFullBackupRestoreObserver;
21import android.app.backup.IRestoreSession;
22import android.content.Context;
23import android.content.Intent;
24import android.os.Binder;
25import android.os.Environment;
26import android.os.IBinder;
27import android.os.ParcelFileDescriptor;
28import android.os.Process;
29import android.os.RemoteException;
30import android.os.SystemProperties;
31import android.os.UserHandle;
32import android.util.Slog;
33
34import java.io.File;
35import java.io.FileDescriptor;
36import java.io.IOException;
37import java.io.PrintWriter;
38
39public class Trampoline extends IBackupManager.Stub {
40    static final String TAG = "BackupManagerService";
41    static final boolean DEBUG_TRAMPOLINE = false;
42
43    // When this file is present, the backup service is inactive
44    static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress";
45
46    // Product-level suppression of backup/restore
47    static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable";
48
49    final Context mContext;
50    final File mSuppressFile;   // existence testing & creating synchronized on 'this'
51    final boolean mGlobalDisable;
52    volatile BackupManagerService mService;
53
54    public Trampoline(Context context) {
55        mContext = context;
56        File dir = new File(Environment.getSecureDataDirectory(), "backup");
57        dir.mkdirs();
58        mSuppressFile = new File(dir, BACKUP_SUPPRESS_FILENAME);
59        mGlobalDisable = SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false);
60    }
61
62    // internal control API
63    public void initialize(final int whichUser) {
64        // Note that only the owner user is currently involved in backup/restore
65        if (whichUser == UserHandle.USER_OWNER) {
66            // Does this product support backup/restore at all?
67            if (mGlobalDisable) {
68                Slog.i(TAG, "Backup/restore not supported");
69                return;
70            }
71
72            synchronized (this) {
73                if (!mSuppressFile.exists()) {
74                    mService = new BackupManagerService(mContext, this);
75                } else {
76                    Slog.i(TAG, "Backup inactive in user " + whichUser);
77                }
78            }
79        }
80    }
81
82    public void setBackupServiceActive(final int userHandle, boolean makeActive) {
83        // Only the DPM should be changing the active state of backup
84        final int caller = Binder.getCallingUid();
85        if (caller != Process.SYSTEM_UID
86                && caller != Process.ROOT_UID) {
87            throw new SecurityException("No permission to configure backup activity");
88        }
89
90        if (mGlobalDisable) {
91            Slog.i(TAG, "Backup/restore not supported");
92            return;
93        }
94
95        if (userHandle == UserHandle.USER_OWNER) {
96            synchronized (this) {
97                if (makeActive != isBackupServiceActive(userHandle)) {
98                    Slog.i(TAG, "Making backup "
99                            + (makeActive ? "" : "in") + "active in user " + userHandle);
100                    if (makeActive) {
101                        mService = new BackupManagerService(mContext, this);
102                        mSuppressFile.delete();
103                    } else {
104                        mService = null;
105                        try {
106                            mSuppressFile.createNewFile();
107                        } catch (IOException e) {
108                            Slog.e(TAG, "Unable to persist backup service inactivity");
109                        }
110                    }
111                }
112            }
113        }
114    }
115
116    /**
117     * Querying activity state of backup service. Calling this method before initialize yields
118     * undefined result.
119     * @param userHandle The user in which the activity state of backup service is queried.
120     * @return true if the service is active.
121     */
122    public boolean isBackupServiceActive(final int userHandle) {
123        if (userHandle == UserHandle.USER_OWNER) {
124            synchronized (this) {
125                return mService != null;
126            }
127        }
128        return false;
129    }
130
131    // IBackupManager binder API
132    @Override
133    public void dataChanged(String packageName) throws RemoteException {
134        BackupManagerService svc = mService;
135        if (svc != null) {
136            svc.dataChanged(packageName);
137        }
138    }
139
140    @Override
141    public void clearBackupData(String transportName, String packageName)
142            throws RemoteException {
143        BackupManagerService svc = mService;
144        if (svc != null) {
145            svc.clearBackupData(transportName, packageName);
146        }
147    }
148
149    @Override
150    public void agentConnected(String packageName, IBinder agent) throws RemoteException {
151        BackupManagerService svc = mService;
152        if (svc != null) {
153            svc.agentConnected(packageName, agent);
154        }
155    }
156
157    @Override
158    public void agentDisconnected(String packageName) throws RemoteException {
159        BackupManagerService svc = mService;
160        if (svc != null) {
161            svc.agentDisconnected(packageName);
162        }
163    }
164
165    @Override
166    public void restoreAtInstall(String packageName, int token) throws RemoteException {
167        BackupManagerService svc = mService;
168        if (svc != null) {
169            svc.restoreAtInstall(packageName, token);
170        }
171    }
172
173    @Override
174    public void setBackupEnabled(boolean isEnabled) throws RemoteException {
175        BackupManagerService svc = mService;
176        if (svc != null) {
177            svc.setBackupEnabled(isEnabled);
178        }
179    }
180
181    @Override
182    public void setAutoRestore(boolean doAutoRestore) throws RemoteException {
183        BackupManagerService svc = mService;
184        if (svc != null) {
185            svc.setAutoRestore(doAutoRestore);
186        }
187    }
188
189    @Override
190    public void setBackupProvisioned(boolean isProvisioned) throws RemoteException {
191        BackupManagerService svc = mService;
192        if (svc != null) {
193            svc.setBackupProvisioned(isProvisioned);
194        }
195    }
196
197    @Override
198    public boolean isBackupEnabled() throws RemoteException {
199        BackupManagerService svc = mService;
200        return (svc != null) ? svc.isBackupEnabled() : false;
201    }
202
203    @Override
204    public boolean setBackupPassword(String currentPw, String newPw) throws RemoteException {
205        BackupManagerService svc = mService;
206        return (svc != null) ? svc.setBackupPassword(currentPw, newPw) : false;
207    }
208
209    @Override
210    public boolean hasBackupPassword() throws RemoteException {
211        BackupManagerService svc = mService;
212        return (svc != null) ? svc.hasBackupPassword() : false;
213    }
214
215    @Override
216    public void backupNow() throws RemoteException {
217        BackupManagerService svc = mService;
218        if (svc != null) {
219            svc.backupNow();
220        }
221    }
222
223    @Override
224    public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
225            boolean includeShared, boolean doWidgets, boolean allApps,
226            boolean allIncludesSystem, boolean doCompress, String[] packageNames)
227                    throws RemoteException {
228        BackupManagerService svc = mService;
229        if (svc != null) {
230            svc.fullBackup(fd, includeApks, includeObbs, includeShared, doWidgets,
231                    allApps, allIncludesSystem, doCompress, packageNames);
232        }
233    }
234
235    @Override
236    public void fullTransportBackup(String[] packageNames) throws RemoteException {
237        BackupManagerService svc = mService;
238        if (svc != null) {
239            svc.fullTransportBackup(packageNames);
240        }
241    }
242
243    @Override
244    public void fullRestore(ParcelFileDescriptor fd) throws RemoteException {
245        BackupManagerService svc = mService;
246        if (svc != null) {
247            svc.fullRestore(fd);
248        }
249    }
250
251    @Override
252    public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword,
253            String encryptionPassword, IFullBackupRestoreObserver observer)
254                    throws RemoteException {
255        BackupManagerService svc = mService;
256        if (svc != null) {
257            svc.acknowledgeFullBackupOrRestore(token, allow,
258                    curPassword, encryptionPassword, observer);
259        }
260    }
261
262    @Override
263    public String getCurrentTransport() throws RemoteException {
264        BackupManagerService svc = mService;
265        return (svc != null) ? svc.getCurrentTransport() : null;
266    }
267
268    @Override
269    public String[] listAllTransports() throws RemoteException {
270        BackupManagerService svc = mService;
271        return (svc != null) ? svc.listAllTransports() : null;
272    }
273
274    @Override
275    public String selectBackupTransport(String transport) throws RemoteException {
276        BackupManagerService svc = mService;
277        return (svc != null) ? svc.selectBackupTransport(transport) : null;
278    }
279
280    @Override
281    public Intent getConfigurationIntent(String transport) throws RemoteException {
282        BackupManagerService svc = mService;
283        return (svc != null) ? svc.getConfigurationIntent(transport) : null;
284    }
285
286    @Override
287    public String getDestinationString(String transport) throws RemoteException {
288        BackupManagerService svc = mService;
289        return (svc != null) ? svc.getDestinationString(transport) : null;
290    }
291
292    @Override
293    public Intent getDataManagementIntent(String transport) throws RemoteException {
294        BackupManagerService svc = mService;
295        return (svc != null) ? svc.getDataManagementIntent(transport) : null;
296    }
297
298    @Override
299    public String getDataManagementLabel(String transport) throws RemoteException {
300        BackupManagerService svc = mService;
301        return (svc != null) ? svc.getDataManagementLabel(transport) : null;
302    }
303
304    @Override
305    public IRestoreSession beginRestoreSession(String packageName, String transportID)
306            throws RemoteException {
307        BackupManagerService svc = mService;
308        return (svc != null) ? svc.beginRestoreSession(packageName, transportID) : null;
309    }
310
311    @Override
312    public void opComplete(int token, long result) throws RemoteException {
313        BackupManagerService svc = mService;
314        if (svc != null) {
315            svc.opComplete(token, result);
316        }
317    }
318
319    @Override
320    public long getAvailableRestoreToken(String packageName) {
321        BackupManagerService svc = mService;
322        return (svc != null) ? svc.getAvailableRestoreToken(packageName) : 0;
323    }
324
325    @Override
326    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
327        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
328
329        BackupManagerService svc = mService;
330        if (svc != null) {
331            svc.dump(fd, pw, args);
332        } else {
333            pw.println("Inactive");
334        }
335    }
336
337    // Full backup/restore entry points - non-Binder; called directly
338    // by the full-backup scheduled job
339    /* package */ boolean beginFullBackup(FullBackupJob scheduledJob) {
340        BackupManagerService svc = mService;
341        return (svc != null) ? svc.beginFullBackup(scheduledJob) : false;
342    }
343
344    /* package */ void endFullBackup() {
345        BackupManagerService svc = mService;
346        if (svc != null) {
347            svc.endFullBackup();
348        }
349    }
350}
351