am 62d1e1ef: Scan at boot time to detect newly-present full backup candidates
* commit '62d1e1ef7e04f03c492b49e721ee9773677bba8b': Scan at boot time to detect newly-present full backup candidates
This commit is contained in:
@@ -88,13 +88,13 @@ import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.StringBuilderPrinter;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.backup.IBackupTransport;
|
||||
import com.android.internal.backup.IObbBackupService;
|
||||
import com.android.server.AppWidgetBackupBridge;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
|
||||
import com.android.server.pm.PackageManagerService;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
@@ -589,8 +589,12 @@ public class BackupManagerService {
|
||||
|
||||
File mFullBackupScheduleFile;
|
||||
// If we're running a schedule-driven full backup, this is the task instance doing it
|
||||
PerformFullTransportBackupTask mRunningFullBackupTask; // inside mQueueLock
|
||||
ArrayList<FullBackupEntry> mFullBackupQueue; // inside mQueueLock
|
||||
|
||||
@GuardedBy("mQueueLock")
|
||||
PerformFullTransportBackupTask mRunningFullBackupTask;
|
||||
|
||||
@GuardedBy("mQueueLock")
|
||||
ArrayList<FullBackupEntry> mFullBackupQueue;
|
||||
|
||||
// Utility: build a new random integer token
|
||||
int generateToken() {
|
||||
@@ -1229,8 +1233,10 @@ public class BackupManagerService {
|
||||
}
|
||||
}
|
||||
|
||||
// Resume the full-data backup queue
|
||||
mFullBackupQueue = readFullBackupSchedule();
|
||||
synchronized (mQueueLock) {
|
||||
// Resume the full-data backup queue
|
||||
mFullBackupQueue = readFullBackupSchedule();
|
||||
}
|
||||
|
||||
// Register for broadcasts about package install, etc., so we can
|
||||
// update the provider list.
|
||||
@@ -1248,74 +1254,98 @@ public class BackupManagerService {
|
||||
}
|
||||
|
||||
private ArrayList<FullBackupEntry> readFullBackupSchedule() {
|
||||
boolean changed = false;
|
||||
ArrayList<FullBackupEntry> schedule = null;
|
||||
synchronized (mQueueLock) {
|
||||
if (mFullBackupScheduleFile.exists()) {
|
||||
FileInputStream fstream = null;
|
||||
BufferedInputStream bufStream = null;
|
||||
DataInputStream in = null;
|
||||
try {
|
||||
fstream = new FileInputStream(mFullBackupScheduleFile);
|
||||
bufStream = new BufferedInputStream(fstream);
|
||||
in = new DataInputStream(bufStream);
|
||||
List<PackageInfo> apps =
|
||||
PackageManagerBackupAgent.getStorableApplications(mPackageManager);
|
||||
|
||||
int version = in.readInt();
|
||||
if (version != SCHEDULE_FILE_VERSION) {
|
||||
Slog.e(TAG, "Unknown backup schedule version " + version);
|
||||
return null;
|
||||
}
|
||||
if (mFullBackupScheduleFile.exists()) {
|
||||
FileInputStream fstream = null;
|
||||
BufferedInputStream bufStream = null;
|
||||
DataInputStream in = null;
|
||||
try {
|
||||
fstream = new FileInputStream(mFullBackupScheduleFile);
|
||||
bufStream = new BufferedInputStream(fstream);
|
||||
in = new DataInputStream(bufStream);
|
||||
|
||||
int N = in.readInt();
|
||||
schedule = new ArrayList<FullBackupEntry>(N);
|
||||
for (int i = 0; i < N; i++) {
|
||||
String pkgName = in.readUTF();
|
||||
long lastBackup = in.readLong();
|
||||
try {
|
||||
PackageInfo pkg = mPackageManager.getPackageInfo(pkgName, 0);
|
||||
if (appGetsFullBackup(pkg)
|
||||
&& appIsEligibleForBackup(pkg.applicationInfo)) {
|
||||
schedule.add(new FullBackupEntry(pkgName, lastBackup));
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Package " + pkgName
|
||||
+ " no longer eligible for full backup");
|
||||
}
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
int version = in.readInt();
|
||||
if (version != SCHEDULE_FILE_VERSION) {
|
||||
Slog.e(TAG, "Unknown backup schedule version " + version);
|
||||
return null;
|
||||
}
|
||||
|
||||
final int N = in.readInt();
|
||||
schedule = new ArrayList<FullBackupEntry>(N);
|
||||
|
||||
// HashSet instead of ArraySet specifically because we want the eventual
|
||||
// lookups against O(hundreds) of entries to be as fast as possible, and
|
||||
// we discard the set immediately after the scan so the extra memory
|
||||
// overhead is transient.
|
||||
HashSet<String> foundApps = new HashSet<String>(N);
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
String pkgName = in.readUTF();
|
||||
long lastBackup = in.readLong();
|
||||
foundApps.add(pkgName); // all apps that we've addressed already
|
||||
try {
|
||||
PackageInfo pkg = mPackageManager.getPackageInfo(pkgName, 0);
|
||||
if (appGetsFullBackup(pkg) && appIsEligibleForBackup(pkg.applicationInfo)) {
|
||||
schedule.add(new FullBackupEntry(pkgName, lastBackup));
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Package " + pkgName
|
||||
+ " not installed; dropping from full backup");
|
||||
+ " no longer eligible for full backup");
|
||||
}
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Package " + pkgName
|
||||
+ " not installed; dropping from full backup");
|
||||
}
|
||||
}
|
||||
Collections.sort(schedule);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Unable to read backup schedule", e);
|
||||
mFullBackupScheduleFile.delete();
|
||||
schedule = null;
|
||||
} finally {
|
||||
IoUtils.closeQuietly(in);
|
||||
IoUtils.closeQuietly(bufStream);
|
||||
IoUtils.closeQuietly(fstream);
|
||||
}
|
||||
}
|
||||
|
||||
if (schedule == null) {
|
||||
// no prior queue record, or unable to read it. Set up the queue
|
||||
// from scratch.
|
||||
List<PackageInfo> apps =
|
||||
PackageManagerBackupAgent.getStorableApplications(mPackageManager);
|
||||
final int N = apps.size();
|
||||
schedule = new ArrayList<FullBackupEntry>(N);
|
||||
for (int i = 0; i < N; i++) {
|
||||
PackageInfo info = apps.get(i);
|
||||
if (appGetsFullBackup(info) && appIsEligibleForBackup(info.applicationInfo)) {
|
||||
schedule.add(new FullBackupEntry(info.packageName, 0));
|
||||
// New apps can arrive "out of band" via OTA and similar, so we also need to
|
||||
// scan to make sure that we're tracking all full-backup candidates properly
|
||||
for (PackageInfo app : apps) {
|
||||
if (appGetsFullBackup(app) && appIsEligibleForBackup(app.applicationInfo)) {
|
||||
if (!foundApps.contains(app.packageName)) {
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "New full backup app " + app.packageName + " found");
|
||||
}
|
||||
schedule.add(new FullBackupEntry(app.packageName, 0));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
writeFullBackupScheduleAsync();
|
||||
|
||||
Collections.sort(schedule);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Unable to read backup schedule", e);
|
||||
mFullBackupScheduleFile.delete();
|
||||
schedule = null;
|
||||
} finally {
|
||||
IoUtils.closeQuietly(in);
|
||||
IoUtils.closeQuietly(bufStream);
|
||||
IoUtils.closeQuietly(fstream);
|
||||
}
|
||||
}
|
||||
|
||||
if (schedule == null) {
|
||||
// no prior queue record, or unable to read it. Set up the queue
|
||||
// from scratch.
|
||||
changed = true;
|
||||
schedule = new ArrayList<FullBackupEntry>(apps.size());
|
||||
for (PackageInfo info : apps) {
|
||||
if (appGetsFullBackup(info) && appIsEligibleForBackup(info.applicationInfo)) {
|
||||
schedule.add(new FullBackupEntry(info.packageName, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
writeFullBackupScheduleAsync();
|
||||
}
|
||||
return schedule;
|
||||
}
|
||||
|
||||
@@ -4313,13 +4343,16 @@ public class BackupManagerService {
|
||||
|
||||
// This is also slow but easy for modest numbers of apps: work backwards
|
||||
// from the end of the queue until we find an item whose last backup
|
||||
// time was before this one, then insert this new entry after it.
|
||||
int which;
|
||||
for (which = mFullBackupQueue.size() - 1; which >= 0; which--) {
|
||||
final FullBackupEntry entry = mFullBackupQueue.get(which);
|
||||
if (entry.lastBackup <= lastBackedUp) {
|
||||
mFullBackupQueue.add(which + 1, newEntry);
|
||||
break;
|
||||
// time was before this one, then insert this new entry after it. If we're
|
||||
// adding something new we don't bother scanning, and just prepend.
|
||||
int which = -1;
|
||||
if (lastBackedUp > 0) {
|
||||
for (which = mFullBackupQueue.size() - 1; which >= 0; which--) {
|
||||
final FullBackupEntry entry = mFullBackupQueue.get(which);
|
||||
if (entry.lastBackup <= lastBackedUp) {
|
||||
mFullBackupQueue.add(which + 1, newEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (which < 0) {
|
||||
|
||||
Reference in New Issue
Block a user