Loading core/java/android/app/backup/IBackupManager.aidl +12 −0 Original line number Diff line number Diff line Loading @@ -291,4 +291,16 @@ interface IBackupManager { * {@hide} */ void opComplete(int token); /** * Make the device's backup and restore machinery (in)active. When it is inactive, * the device will not perform any backup operations, nor will it deliver data for * restore, although clients can still safely call BackupManager methods. * * @param whichUser User handle of the defined user whose backup active state * is to be adjusted. * @param makeActive {@code true} when backup services are to be made active; * {@code false} otherwise. */ void setBackupServiceActive(int whichUser, boolean makeActive); } services/backup/java/com/android/server/backup/BackupManagerService.java +19 −18 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ import javax.crypto.spec.SecretKeySpec; import libcore.io.IoUtils; public class BackupManagerService extends IBackupManager.Stub { public class BackupManagerService { private static final String TAG = "BackupManagerService"; private static final boolean DEBUG = true; Loading Loading @@ -322,8 +322,12 @@ public class BackupManagerService extends IBackupManager.Stub { // Watch the device provisioning operation during setup ContentObserver mProvisionedObserver; static BackupManagerService sInstance; static BackupManagerService getInstance() { // The published binder is actually to a singleton trampoline object that calls // through to the proper code. This indirection lets us turn down the heavy // implementation object on the fly without disturbing binders that have been // cached elsewhere in the system. static Trampoline sInstance; static Trampoline getInstance() { // Always constructed during system bringup, so no need to lazy-init return sInstance; } Loading @@ -332,7 +336,7 @@ public class BackupManagerService extends IBackupManager.Stub { public Lifecycle(Context context) { super(context); sInstance = new BackupManagerService(context); sInstance = new Trampoline(context); } @Override Loading @@ -342,11 +346,17 @@ public class BackupManagerService extends IBackupManager.Stub { @Override public void onBootPhase(int phase) { if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { if (phase == PHASE_SYSTEM_SERVICES_READY) { sInstance.initialize(UserHandle.USER_OWNER); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { ContentResolver r = sInstance.mContext.getContentResolver(); boolean areEnabled = Settings.Secure.getInt(r, Settings.Secure.BACKUP_ENABLED, 0) != 0; try { sInstance.setBackupEnabled(areEnabled); } catch (RemoteException e) { // can't happen; it's a local object } } } } Loading Loading @@ -934,7 +944,7 @@ public class BackupManagerService extends IBackupManager.Stub { // ----- Main service implementation ----- public BackupManagerService(Context context) { public BackupManagerService(Context context, Trampoline parent) { mContext = context; mPackageManager = context.getPackageManager(); mPackageManagerBinder = AppGlobals.getPackageManager(); Loading @@ -944,7 +954,7 @@ public class BackupManagerService extends IBackupManager.Stub { mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); mBackupManagerBinder = asInterface(asBinder()); mBackupManagerBinder = Trampoline.asInterface(parent.asBinder()); // spin up the backup/restore handler thread mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND); Loading Loading @@ -1451,7 +1461,6 @@ public class BackupManagerService extends IBackupManager.Stub { return false; } @Override public boolean setBackupPassword(String currentPw, String newPw) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "setBackupPassword"); Loading Loading @@ -1532,7 +1541,6 @@ public class BackupManagerService extends IBackupManager.Stub { return false; } @Override public boolean hasBackupPassword() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "hasBackupPassword"); Loading Loading @@ -8145,7 +8153,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // // This is the variant used by 'adb backup'; it requires on-screen confirmation // by the user because it can be used to offload data over untrusted USB. @Override public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, boolean doAllApps, boolean includeSystem, boolean compress, String[] pkgList) { Loading Loading @@ -8217,7 +8224,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } @Override public void fullTransportBackup(String[] pkgNames) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullTransportBackup"); Loading Loading @@ -8247,7 +8253,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } @Override public void fullRestore(ParcelFileDescriptor fd) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullRestore"); Loading Loading @@ -8343,7 +8348,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // Confirm that the previously-requested full backup/restore operation can proceed. This // is used to require a user-facing disclosure about the operation. @Override public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword, String encPpassword, IFullBackupRestoreObserver observer) { if (DEBUG) Slog.d(TAG, "acknowledgeFullBackupOrRestore : token=" + token Loading Loading @@ -8391,8 +8395,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } // Enable/disable the backup service @Override // Enable/disable backups public void setBackupEnabled(boolean enable) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "setBackupEnabled"); Loading Loading @@ -8798,7 +8801,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // Note that a currently-active backup agent has notified us that it has // completed the given outstanding asynchronous backup/restore operation. @Override public void opComplete(int token) { if (MORE_DEBUG) Slog.v(TAG, "opComplete: " + Integer.toHexString(token)); Operation op = null; Loading Loading @@ -9147,7 +9149,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); Loading services/backup/java/com/android/server/backup/FullBackupJob.java +2 −2 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ public class FullBackupJob extends JobService { @Override public boolean onStartJob(JobParameters params) { mParams = params; BackupManagerService service = BackupManagerService.getInstance(); Trampoline service = BackupManagerService.getInstance(); return service.beginFullBackup(this); } Loading @@ -67,7 +67,7 @@ public class FullBackupJob extends JobService { public boolean onStopJob(JobParameters params) { if (mParams != null) { mParams = null; BackupManagerService service = BackupManagerService.getInstance(); Trampoline service = BackupManagerService.getInstance(); service.endFullBackup(); } return false; Loading services/backup/java/com/android/server/backup/Trampoline.java 0 → 100644 +327 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.backup; import android.app.backup.IBackupManager; import android.app.backup.IFullBackupRestoreObserver; import android.app.backup.IRestoreSession; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.Environment; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; import android.util.Slog; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; public class Trampoline extends IBackupManager.Stub { static final String TAG = "BackupManagerService"; static final boolean DEBUG_TRAMPOLINE = false; // When this file is present, the backup service is inactive static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress"; // Product-level suppression of backup/restore static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable"; final Context mContext; final File mSuppressFile; // existence testing & creating synchronized on 'this' final boolean mGlobalDisable; volatile BackupManagerService mService; public Trampoline(Context context) { mContext = context; File dir = new File(Environment.getSecureDataDirectory(), "backup"); dir.mkdirs(); mSuppressFile = new File(dir, BACKUP_SUPPRESS_FILENAME); mGlobalDisable = SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false); } // internal control API public void initialize(final int whichUser) { // Note that only the owner user is currently involved in backup/restore if (whichUser == UserHandle.USER_OWNER) { // Does this product support backup/restore at all? if (mGlobalDisable) { Slog.i(TAG, "Backup/restore not supported"); return; } synchronized (this) { if (!mSuppressFile.exists()) { mService = new BackupManagerService(mContext, this); } else { Slog.i(TAG, "Backup inactive in user " + whichUser); } } } } public void setBackupServiceActive(final int userHandle, boolean makeActive) { // Only the DPM should be changing the active state of backup final int caller = Binder.getCallingUid(); if (caller != Process.SYSTEM_UID && caller != Process.ROOT_UID) { throw new SecurityException("No permission to configure backup activity"); } if (mGlobalDisable) { Slog.i(TAG, "Backup/restore not supported"); return; } if (userHandle == UserHandle.USER_OWNER) { synchronized (this) { if (makeActive != (mService != null)) { Slog.i(TAG, "Making backup " + (makeActive ? "" : "in") + "active in user " + userHandle); if (makeActive) { mService = new BackupManagerService(mContext, this); mSuppressFile.delete(); } else { mService = null; try { mSuppressFile.createNewFile(); } catch (IOException e) { Slog.e(TAG, "Unable to persist backup service inactivity"); } } } } } } // IBackupManager binder API @Override public void dataChanged(String packageName) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.dataChanged(packageName); } } @Override public void clearBackupData(String transportName, String packageName) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.clearBackupData(transportName, packageName); } } @Override public void agentConnected(String packageName, IBinder agent) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.agentConnected(packageName, agent); } } @Override public void agentDisconnected(String packageName) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.agentDisconnected(packageName); } } @Override public void restoreAtInstall(String packageName, int token) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.restoreAtInstall(packageName, token); } } @Override public void setBackupEnabled(boolean isEnabled) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.setBackupEnabled(isEnabled); } } @Override public void setAutoRestore(boolean doAutoRestore) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.setAutoRestore(doAutoRestore); } } @Override public void setBackupProvisioned(boolean isProvisioned) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.setBackupProvisioned(isProvisioned); } } @Override public boolean isBackupEnabled() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.isBackupEnabled() : false; } @Override public boolean setBackupPassword(String currentPw, String newPw) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.setBackupPassword(currentPw, newPw) : false; } @Override public boolean hasBackupPassword() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.hasBackupPassword() : false; } @Override public void backupNow() throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.backupNow(); } } @Override public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, boolean allApps, boolean allIncludesSystem, boolean doCompress, String[] packageNames) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.fullBackup(fd, includeApks, includeObbs, includeShared, doWidgets, allApps, allIncludesSystem, doCompress, packageNames); } } @Override public void fullTransportBackup(String[] packageNames) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.fullTransportBackup(packageNames); } } @Override public void fullRestore(ParcelFileDescriptor fd) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.fullRestore(fd); } } @Override public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword, String encryptionPassword, IFullBackupRestoreObserver observer) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.acknowledgeFullBackupOrRestore(token, allow, curPassword, encryptionPassword, observer); } } @Override public String getCurrentTransport() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getCurrentTransport() : null; } @Override public String[] listAllTransports() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.listAllTransports() : null; } @Override public String selectBackupTransport(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.selectBackupTransport(transport) : null; } @Override public Intent getConfigurationIntent(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getConfigurationIntent(transport) : null; } @Override public String getDestinationString(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getDestinationString(transport) : null; } @Override public Intent getDataManagementIntent(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getDataManagementIntent(transport) : null; } @Override public String getDataManagementLabel(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getDataManagementLabel(transport) : null; } @Override public IRestoreSession beginRestoreSession(String packageName, String transportID) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.beginRestoreSession(packageName, transportID) : null; } @Override public void opComplete(int token) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.opComplete(token); } } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { BackupManagerService svc = mService; if (svc != null) { svc.dump(fd, pw, args); } else { pw.println("Inactive"); } } // Full backup/restore entry points - non-Binder; called directly // by the full-backup scheduled job /* package */ boolean beginFullBackup(FullBackupJob scheduledJob) { BackupManagerService svc = mService; return (svc != null) ? svc.beginFullBackup(scheduledJob) : false; } /* package */ void endFullBackup() { BackupManagerService svc = mService; if (svc != null) { svc.endFullBackup(); } } } Loading
core/java/android/app/backup/IBackupManager.aidl +12 −0 Original line number Diff line number Diff line Loading @@ -291,4 +291,16 @@ interface IBackupManager { * {@hide} */ void opComplete(int token); /** * Make the device's backup and restore machinery (in)active. When it is inactive, * the device will not perform any backup operations, nor will it deliver data for * restore, although clients can still safely call BackupManager methods. * * @param whichUser User handle of the defined user whose backup active state * is to be adjusted. * @param makeActive {@code true} when backup services are to be made active; * {@code false} otherwise. */ void setBackupServiceActive(int whichUser, boolean makeActive); }
services/backup/java/com/android/server/backup/BackupManagerService.java +19 −18 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ import javax.crypto.spec.SecretKeySpec; import libcore.io.IoUtils; public class BackupManagerService extends IBackupManager.Stub { public class BackupManagerService { private static final String TAG = "BackupManagerService"; private static final boolean DEBUG = true; Loading Loading @@ -322,8 +322,12 @@ public class BackupManagerService extends IBackupManager.Stub { // Watch the device provisioning operation during setup ContentObserver mProvisionedObserver; static BackupManagerService sInstance; static BackupManagerService getInstance() { // The published binder is actually to a singleton trampoline object that calls // through to the proper code. This indirection lets us turn down the heavy // implementation object on the fly without disturbing binders that have been // cached elsewhere in the system. static Trampoline sInstance; static Trampoline getInstance() { // Always constructed during system bringup, so no need to lazy-init return sInstance; } Loading @@ -332,7 +336,7 @@ public class BackupManagerService extends IBackupManager.Stub { public Lifecycle(Context context) { super(context); sInstance = new BackupManagerService(context); sInstance = new Trampoline(context); } @Override Loading @@ -342,11 +346,17 @@ public class BackupManagerService extends IBackupManager.Stub { @Override public void onBootPhase(int phase) { if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { if (phase == PHASE_SYSTEM_SERVICES_READY) { sInstance.initialize(UserHandle.USER_OWNER); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { ContentResolver r = sInstance.mContext.getContentResolver(); boolean areEnabled = Settings.Secure.getInt(r, Settings.Secure.BACKUP_ENABLED, 0) != 0; try { sInstance.setBackupEnabled(areEnabled); } catch (RemoteException e) { // can't happen; it's a local object } } } } Loading Loading @@ -934,7 +944,7 @@ public class BackupManagerService extends IBackupManager.Stub { // ----- Main service implementation ----- public BackupManagerService(Context context) { public BackupManagerService(Context context, Trampoline parent) { mContext = context; mPackageManager = context.getPackageManager(); mPackageManagerBinder = AppGlobals.getPackageManager(); Loading @@ -944,7 +954,7 @@ public class BackupManagerService extends IBackupManager.Stub { mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); mBackupManagerBinder = asInterface(asBinder()); mBackupManagerBinder = Trampoline.asInterface(parent.asBinder()); // spin up the backup/restore handler thread mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND); Loading Loading @@ -1451,7 +1461,6 @@ public class BackupManagerService extends IBackupManager.Stub { return false; } @Override public boolean setBackupPassword(String currentPw, String newPw) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "setBackupPassword"); Loading Loading @@ -1532,7 +1541,6 @@ public class BackupManagerService extends IBackupManager.Stub { return false; } @Override public boolean hasBackupPassword() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "hasBackupPassword"); Loading Loading @@ -8145,7 +8153,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // // This is the variant used by 'adb backup'; it requires on-screen confirmation // by the user because it can be used to offload data over untrusted USB. @Override public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, boolean doAllApps, boolean includeSystem, boolean compress, String[] pkgList) { Loading Loading @@ -8217,7 +8224,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } @Override public void fullTransportBackup(String[] pkgNames) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullTransportBackup"); Loading Loading @@ -8247,7 +8253,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } @Override public void fullRestore(ParcelFileDescriptor fd) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullRestore"); Loading Loading @@ -8343,7 +8348,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // Confirm that the previously-requested full backup/restore operation can proceed. This // is used to require a user-facing disclosure about the operation. @Override public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword, String encPpassword, IFullBackupRestoreObserver observer) { if (DEBUG) Slog.d(TAG, "acknowledgeFullBackupOrRestore : token=" + token Loading Loading @@ -8391,8 +8395,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } // Enable/disable the backup service @Override // Enable/disable backups public void setBackupEnabled(boolean enable) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "setBackupEnabled"); Loading Loading @@ -8798,7 +8801,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // Note that a currently-active backup agent has notified us that it has // completed the given outstanding asynchronous backup/restore operation. @Override public void opComplete(int token) { if (MORE_DEBUG) Slog.v(TAG, "opComplete: " + Integer.toHexString(token)); Operation op = null; Loading Loading @@ -9147,7 +9149,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF } } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); Loading
services/backup/java/com/android/server/backup/FullBackupJob.java +2 −2 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ public class FullBackupJob extends JobService { @Override public boolean onStartJob(JobParameters params) { mParams = params; BackupManagerService service = BackupManagerService.getInstance(); Trampoline service = BackupManagerService.getInstance(); return service.beginFullBackup(this); } Loading @@ -67,7 +67,7 @@ public class FullBackupJob extends JobService { public boolean onStopJob(JobParameters params) { if (mParams != null) { mParams = null; BackupManagerService service = BackupManagerService.getInstance(); Trampoline service = BackupManagerService.getInstance(); service.endFullBackup(); } return false; Loading
services/backup/java/com/android/server/backup/Trampoline.java 0 → 100644 +327 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.backup; import android.app.backup.IBackupManager; import android.app.backup.IFullBackupRestoreObserver; import android.app.backup.IRestoreSession; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.Environment; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; import android.util.Slog; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; public class Trampoline extends IBackupManager.Stub { static final String TAG = "BackupManagerService"; static final boolean DEBUG_TRAMPOLINE = false; // When this file is present, the backup service is inactive static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress"; // Product-level suppression of backup/restore static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable"; final Context mContext; final File mSuppressFile; // existence testing & creating synchronized on 'this' final boolean mGlobalDisable; volatile BackupManagerService mService; public Trampoline(Context context) { mContext = context; File dir = new File(Environment.getSecureDataDirectory(), "backup"); dir.mkdirs(); mSuppressFile = new File(dir, BACKUP_SUPPRESS_FILENAME); mGlobalDisable = SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false); } // internal control API public void initialize(final int whichUser) { // Note that only the owner user is currently involved in backup/restore if (whichUser == UserHandle.USER_OWNER) { // Does this product support backup/restore at all? if (mGlobalDisable) { Slog.i(TAG, "Backup/restore not supported"); return; } synchronized (this) { if (!mSuppressFile.exists()) { mService = new BackupManagerService(mContext, this); } else { Slog.i(TAG, "Backup inactive in user " + whichUser); } } } } public void setBackupServiceActive(final int userHandle, boolean makeActive) { // Only the DPM should be changing the active state of backup final int caller = Binder.getCallingUid(); if (caller != Process.SYSTEM_UID && caller != Process.ROOT_UID) { throw new SecurityException("No permission to configure backup activity"); } if (mGlobalDisable) { Slog.i(TAG, "Backup/restore not supported"); return; } if (userHandle == UserHandle.USER_OWNER) { synchronized (this) { if (makeActive != (mService != null)) { Slog.i(TAG, "Making backup " + (makeActive ? "" : "in") + "active in user " + userHandle); if (makeActive) { mService = new BackupManagerService(mContext, this); mSuppressFile.delete(); } else { mService = null; try { mSuppressFile.createNewFile(); } catch (IOException e) { Slog.e(TAG, "Unable to persist backup service inactivity"); } } } } } } // IBackupManager binder API @Override public void dataChanged(String packageName) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.dataChanged(packageName); } } @Override public void clearBackupData(String transportName, String packageName) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.clearBackupData(transportName, packageName); } } @Override public void agentConnected(String packageName, IBinder agent) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.agentConnected(packageName, agent); } } @Override public void agentDisconnected(String packageName) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.agentDisconnected(packageName); } } @Override public void restoreAtInstall(String packageName, int token) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.restoreAtInstall(packageName, token); } } @Override public void setBackupEnabled(boolean isEnabled) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.setBackupEnabled(isEnabled); } } @Override public void setAutoRestore(boolean doAutoRestore) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.setAutoRestore(doAutoRestore); } } @Override public void setBackupProvisioned(boolean isProvisioned) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.setBackupProvisioned(isProvisioned); } } @Override public boolean isBackupEnabled() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.isBackupEnabled() : false; } @Override public boolean setBackupPassword(String currentPw, String newPw) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.setBackupPassword(currentPw, newPw) : false; } @Override public boolean hasBackupPassword() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.hasBackupPassword() : false; } @Override public void backupNow() throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.backupNow(); } } @Override public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, boolean allApps, boolean allIncludesSystem, boolean doCompress, String[] packageNames) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.fullBackup(fd, includeApks, includeObbs, includeShared, doWidgets, allApps, allIncludesSystem, doCompress, packageNames); } } @Override public void fullTransportBackup(String[] packageNames) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.fullTransportBackup(packageNames); } } @Override public void fullRestore(ParcelFileDescriptor fd) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.fullRestore(fd); } } @Override public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword, String encryptionPassword, IFullBackupRestoreObserver observer) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.acknowledgeFullBackupOrRestore(token, allow, curPassword, encryptionPassword, observer); } } @Override public String getCurrentTransport() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getCurrentTransport() : null; } @Override public String[] listAllTransports() throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.listAllTransports() : null; } @Override public String selectBackupTransport(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.selectBackupTransport(transport) : null; } @Override public Intent getConfigurationIntent(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getConfigurationIntent(transport) : null; } @Override public String getDestinationString(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getDestinationString(transport) : null; } @Override public Intent getDataManagementIntent(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getDataManagementIntent(transport) : null; } @Override public String getDataManagementLabel(String transport) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.getDataManagementLabel(transport) : null; } @Override public IRestoreSession beginRestoreSession(String packageName, String transportID) throws RemoteException { BackupManagerService svc = mService; return (svc != null) ? svc.beginRestoreSession(packageName, transportID) : null; } @Override public void opComplete(int token) throws RemoteException { BackupManagerService svc = mService; if (svc != null) { svc.opComplete(token); } } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { BackupManagerService svc = mService; if (svc != null) { svc.dump(fd, pw, args); } else { pw.println("Inactive"); } } // Full backup/restore entry points - non-Binder; called directly // by the full-backup scheduled job /* package */ boolean beginFullBackup(FullBackupJob scheduledJob) { BackupManagerService svc = mService; return (svc != null) ? svc.beginFullBackup(scheduledJob) : false; } /* package */ void endFullBackup() { BackupManagerService svc = mService; if (svc != null) { svc.endFullBackup(); } } }