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