diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 7492629b6dab6..67d3930436689 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2809,6 +2809,15 @@ class ActivityManagerProxy implements IActivityManager return success; } + public void clearPendingBackup() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(CLEAR_PENDING_BACKUP_TRANSACTION, data, reply, 0); + reply.recycle(); + data.recycle(); + } + public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 5f65f0804eecc..456d757909c2d 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -29,6 +29,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ProviderInfo; @@ -2396,12 +2397,31 @@ public final class ActivityThread { private void handleCreateBackupAgent(CreateBackupAgentData data) { if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data); + // Sanity check the requested target package's uid against ours + try { + PackageInfo requestedPackage = getPackageManager().getPackageInfo( + data.appInfo.packageName, 0, UserHandle.myUserId()); + if (requestedPackage.applicationInfo.uid != Process.myUid()) { + Slog.w(TAG, "Asked to instantiate non-matching package " + + data.appInfo.packageName); + return; + } + } catch (RemoteException e) { + Slog.e(TAG, "Can't reach package manager", e); + return; + } + // no longer idle; we have backup work to do unscheduleGcIdler(); // instantiate the BackupAgent class named in the manifest LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); String packageName = packageInfo.mPackageName; + if (packageName == null) { + Slog.d(TAG, "Asked to create backup agent for nonexistent package"); + return; + } + if (mBackupAgents.get(packageName) != null) { Slog.d(TAG, "BackupAgent " + " for " + packageName + " already exists"); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 97250e9f71712..8fc1c86668148 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -152,6 +152,7 @@ public interface IActivityManager extends IInterface { public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode) throws RemoteException; + public void clearPendingBackup() throws RemoteException; public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException; public void unbindBackupAgent(ApplicationInfo appInfo) throws RemoteException; public void killApplicationProcess(String processName, int uid) throws RemoteException; @@ -619,4 +620,5 @@ public interface IActivityManager extends IInterface { int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156; int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157; int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158; + int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159; } diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 9f01ecae36b6a..f241c8090dbc3 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -1474,6 +1474,7 @@ class BackupManagerService extends IBackupManager.Stub { if (MORE_DEBUG) Slog.v(TAG, " removing participant " + packageName); removeEverBackedUp(packageName); set.remove(packageName); + mPendingBackups.remove(packageName); } } @@ -1625,6 +1626,7 @@ class BackupManagerService extends IBackupManager.Stub { } catch (InterruptedException e) { // just bail if (DEBUG) Slog.w(TAG, "Interrupted: " + e); + mActivityManager.clearPendingBackup(); return null; } } @@ -1632,6 +1634,7 @@ class BackupManagerService extends IBackupManager.Stub { // if we timed out with no connect, abort and move on if (mConnecting == true) { Slog.w(TAG, "Timeout waiting for agent " + app); + mActivityManager.clearPendingBackup(); return null; } if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 7132e1e66eb7e..1737876a2ff7f 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -11119,8 +11119,8 @@ public final class ActivityManagerService extends ActivityManagerNative // instantiated. The backup agent will invoke backupAgentCreated() on the // activity manager to announce its creation. public boolean bindBackupAgent(ApplicationInfo app, int backupMode) { - if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode); - enforceCallingPermission("android.permission.BACKUP", "startBackupAgent"); + if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + app + " mode=" + backupMode); + enforceCallingPermission("android.permission.BACKUP", "bindBackupAgent"); synchronized(this) { // !!! TODO: currently no check here that we're already bound @@ -11181,6 +11181,17 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } + @Override + public void clearPendingBackup() { + if (DEBUG_BACKUP) Slog.v(TAG, "clearPendingBackup"); + enforceCallingPermission("android.permission.BACKUP", "clearPendingBackup"); + + synchronized (this) { + mBackupTarget = null; + mBackupAppName = null; + } + } + // A backup agent has just come up public void backupAgentCreated(String agentPackageName, IBinder agent) { if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName @@ -11217,32 +11228,34 @@ public final class ActivityManagerService extends ActivityManagerNative } synchronized(this) { - if (mBackupAppName == null) { - Slog.w(TAG, "Unbinding backup agent with no active backup"); - return; - } - - if (!mBackupAppName.equals(appInfo.packageName)) { - Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target"); - return; - } - - ProcessRecord proc = mBackupTarget.app; - mBackupTarget = null; - mBackupAppName = null; - - // Not backing this app up any more; reset its OOM adjustment - updateOomAdjLocked(proc); - - // If the app crashed during backup, 'thread' will be null here - if (proc.thread != null) { - try { - proc.thread.scheduleDestroyBackupAgent(appInfo, - compatibilityInfoForPackageLocked(appInfo)); - } catch (Exception e) { - Slog.e(TAG, "Exception when unbinding backup agent:"); - e.printStackTrace(); + try { + if (mBackupAppName == null) { + Slog.w(TAG, "Unbinding backup agent with no active backup"); + return; } + + if (!mBackupAppName.equals(appInfo.packageName)) { + Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target"); + return; + } + + // Not backing this app up any more; reset its OOM adjustment + final ProcessRecord proc = mBackupTarget.app; + updateOomAdjLocked(proc); + + // If the app crashed during backup, 'thread' will be null here + if (proc.thread != null) { + try { + proc.thread.scheduleDestroyBackupAgent(appInfo, + compatibilityInfoForPackageLocked(appInfo)); + } catch (Exception e) { + Slog.e(TAG, "Exception when unbinding backup agent:"); + e.printStackTrace(); + } + } + } finally { + mBackupTarget = null; + mBackupAppName = null; } } }