Skip to content

Commit 3df92c5

Browse files
Christopher TateAndroid (Google) Code Review
authored andcommitted
Merge "Fix uninstallation tracking in the Backup Manager"
2 parents 65dd394 + a3d5534 commit 3df92c5

File tree

1 file changed

+82
-138
lines changed

1 file changed

+82
-138
lines changed

services/java/com/android/server/BackupManagerService.java

Lines changed: 82 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ class BackupManagerService extends IBackupManager.Stub {
201201
BackupHandler mBackupHandler;
202202
PendingIntent mRunBackupIntent, mRunInitIntent;
203203
BroadcastReceiver mRunBackupReceiver, mRunInitReceiver;
204-
// map UIDs to the set of backup client services within that UID's app set
205-
final SparseArray<HashSet<ApplicationInfo>> mBackupParticipants
206-
= new SparseArray<HashSet<ApplicationInfo>>();
204+
// map UIDs to the set of participating packages under that UID
205+
final SparseArray<HashSet<String>> mBackupParticipants
206+
= new SparseArray<HashSet<String>>();
207207
// set of backup services that have pending changes
208208
class BackupRequest {
209209
public String packageName;
@@ -960,7 +960,6 @@ private void initPackageTracking() {
960960
IntentFilter filter = new IntentFilter();
961961
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
962962
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
963-
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
964963
filter.addDataScheme("package");
965964
mContext.registerReceiver(mBroadcastReceiver, filter);
966965
// Register for events related to sdcard installation.
@@ -1239,12 +1238,13 @@ void resetBackupState(File stateFileDir) {
12391238

12401239
// Enqueue a new backup of every participant
12411240
synchronized (mBackupParticipants) {
1242-
int N = mBackupParticipants.size();
1241+
final int N = mBackupParticipants.size();
12431242
for (int i=0; i<N; i++) {
1244-
int uid = mBackupParticipants.keyAt(i);
1245-
HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
1246-
for (ApplicationInfo app: participants) {
1247-
dataChangedImpl(app.packageName);
1243+
HashSet<String> participants = mBackupParticipants.valueAt(i);
1244+
if (participants != null) {
1245+
for (String packageName : participants) {
1246+
dataChangedImpl(packageName);
1247+
}
12481248
}
12491249
}
12501250
}
@@ -1302,8 +1302,7 @@ public void onReceive(Context context, Intent intent) {
13021302
Bundle extras = intent.getExtras();
13031303
String pkgList[] = null;
13041304
if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
1305-
Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
1306-
Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
1305+
Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
13071306
Uri uri = intent.getData();
13081307
if (uri == null) {
13091308
return;
@@ -1312,14 +1311,8 @@ public void onReceive(Context context, Intent intent) {
13121311
if (pkgName != null) {
13131312
pkgList = new String[] { pkgName };
13141313
}
1315-
if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
1316-
// use the existing "add with replacement" logic
1317-
if (MORE_DEBUG) Slog.d(TAG, "PACKAGE_REPLACED, updating package " + pkgName);
1318-
added = replacing = true;
1319-
} else {
1320-
added = Intent.ACTION_PACKAGE_ADDED.equals(action);
1321-
replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
1322-
}
1314+
added = Intent.ACTION_PACKAGE_ADDED.equals(action);
1315+
replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
13231316
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
13241317
added = true;
13251318
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -1331,20 +1324,23 @@ public void onReceive(Context context, Intent intent) {
13311324
if (pkgList == null || pkgList.length == 0) {
13321325
return;
13331326
}
1327+
1328+
final int uid = extras.getInt(Intent.EXTRA_UID);
13341329
if (added) {
13351330
synchronized (mBackupParticipants) {
13361331
if (replacing) {
1337-
updatePackageParticipantsLocked(pkgList);
1338-
} else {
1339-
addPackageParticipantsLocked(pkgList);
1332+
// This is the package-replaced case; we just remove the entry
1333+
// under the old uid and fall through to re-add.
1334+
removePackageParticipantsLocked(pkgList, uid);
13401335
}
1336+
addPackageParticipantsLocked(pkgList);
13411337
}
13421338
} else {
13431339
if (replacing) {
13441340
// The package is being updated. We'll receive a PACKAGE_ADDED shortly.
13451341
} else {
13461342
synchronized (mBackupParticipants) {
1347-
removePackageParticipantsLocked(pkgList);
1343+
removePackageParticipantsLocked(pkgList, uid);
13481344
}
13491345
}
13501346
}
@@ -1391,12 +1387,12 @@ private void addPackageParticipantsLockedInner(String packageName,
13911387
for (PackageInfo pkg : targetPkgs) {
13921388
if (packageName == null || pkg.packageName.equals(packageName)) {
13931389
int uid = pkg.applicationInfo.uid;
1394-
HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
1390+
HashSet<String> set = mBackupParticipants.get(uid);
13951391
if (set == null) {
1396-
set = new HashSet<ApplicationInfo>();
1392+
set = new HashSet<String>();
13971393
mBackupParticipants.put(uid, set);
13981394
}
1399-
set.add(pkg.applicationInfo);
1395+
set.add(pkg.packageName);
14001396
if (MORE_DEBUG) Slog.v(TAG, "Agent found; added");
14011397

14021398
// If we've never seen this app before, schedule a backup for it
@@ -1410,63 +1406,36 @@ private void addPackageParticipantsLockedInner(String packageName,
14101406
}
14111407

14121408
// Remove the given packages' entries from our known active set.
1413-
void removePackageParticipantsLocked(String[] packageNames) {
1409+
void removePackageParticipantsLocked(String[] packageNames, int oldUid) {
14141410
if (packageNames == null) {
14151411
Slog.w(TAG, "removePackageParticipants with null list");
14161412
return;
14171413
}
14181414

1419-
if (DEBUG) Slog.v(TAG, "removePackageParticipantsLocked: #" + packageNames.length);
1420-
List<PackageInfo> knownPackages = allAgentPackages();
1415+
if (DEBUG) Slog.v(TAG, "removePackageParticipantsLocked: uid=" + oldUid
1416+
+ " #" + packageNames.length);
14211417
for (String pkg : packageNames) {
1422-
removePackageParticipantsLockedInner(pkg, knownPackages);
1418+
// Known previous UID, so we know which package set to check
1419+
HashSet<String> set = mBackupParticipants.get(oldUid);
1420+
if (set != null && set.contains(pkg)) {
1421+
removePackageFromSetLocked(set, pkg);
1422+
if (set.isEmpty()) {
1423+
if (MORE_DEBUG) Slog.v(TAG, " last one of this uid; purging set");
1424+
mBackupParticipants.remove(oldUid);
1425+
}
1426+
}
14231427
}
14241428
}
14251429

1426-
private void removePackageParticipantsLockedInner(String packageName,
1427-
List<PackageInfo> allPackages) {
1428-
if (MORE_DEBUG) {
1429-
Slog.v(TAG, "removePackageParticipantsLockedInner (" + packageName
1430-
+ ") removing from " + allPackages.size() + " entries");
1431-
for (PackageInfo p : allPackages) {
1432-
Slog.v(TAG, " - " + p.packageName);
1433-
}
1434-
}
1435-
for (PackageInfo pkg : allPackages) {
1436-
if (packageName == null || pkg.packageName.equals(packageName)) {
1437-
/*
1438-
int uid = -1;
1439-
try {
1440-
PackageInfo info = mPackageManager.getPackageInfo(packageName, 0);
1441-
uid = info.applicationInfo.uid;
1442-
} catch (NameNotFoundException e) {
1443-
// we don't know this package name, so just skip it for now
1444-
continue;
1445-
}
1446-
*/
1447-
final int uid = pkg.applicationInfo.uid;
1448-
if (MORE_DEBUG) Slog.i(TAG, " found pkg " + packageName + " uid=" + uid);
1449-
1450-
HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
1451-
if (set != null) {
1452-
// Find the existing entry with the same package name, and remove it.
1453-
// We can't just remove(app) because the instances are different.
1454-
for (ApplicationInfo entry: set) {
1455-
if (MORE_DEBUG) Slog.i(TAG, " checking against " + entry.packageName);
1456-
if (entry.packageName.equals(pkg)) {
1457-
if (MORE_DEBUG) Slog.v(TAG, " removing participant " + pkg);
1458-
set.remove(entry);
1459-
removeEverBackedUp(pkg.packageName);
1460-
break;
1461-
}
1462-
}
1463-
if (set.size() == 0) {
1464-
mBackupParticipants.delete(uid);
1465-
}
1466-
} else {
1467-
if (MORE_DEBUG) Slog.i(TAG, " ... not found in uid mapping");
1468-
}
1469-
}
1430+
private void removePackageFromSetLocked(final HashSet<String> set,
1431+
final String packageName) {
1432+
if (set.contains(packageName)) {
1433+
// Found it. Remove this one package from the bookkeeping, and
1434+
// if it's the last participating app under this uid we drop the
1435+
// (now-empty) set as well.
1436+
if (MORE_DEBUG) Slog.v(TAG, " removing participant " + packageName);
1437+
removeEverBackedUp(packageName);
1438+
set.remove(packageName);
14701439
}
14711440
}
14721441

@@ -1497,24 +1466,6 @@ List<PackageInfo> allAgentPackages() {
14971466
return packages;
14981467
}
14991468

1500-
// Reset the given package's known backup participants. Unlike add/remove, the update
1501-
// action cannot be passed a null package name.
1502-
void updatePackageParticipantsLocked(String[] packageNames) {
1503-
if (packageNames == null) {
1504-
Slog.e(TAG, "updatePackageParticipants called with null package list");
1505-
return;
1506-
}
1507-
if (DEBUG) Slog.v(TAG, "updatePackageParticipantsLocked: #" + packageNames.length);
1508-
1509-
if (packageNames.length > 0) {
1510-
List<PackageInfo> allApps = allAgentPackages();
1511-
for (String packageName : packageNames) {
1512-
removePackageParticipantsLockedInner(packageName, allApps);
1513-
addPackageParticipantsLockedInner(packageName, allApps);
1514-
}
1515-
}
1516-
}
1517-
15181469
// Called from the backup task: record that the given app has been successfully
15191470
// backed up at least once
15201471
void logBackupComplete(String packageName) {
@@ -4772,11 +4723,11 @@ public void run() {
47724723
}
47734724

47744725
private void dataChangedImpl(String packageName) {
4775-
HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
4726+
HashSet<String> targets = dataChangedTargets(packageName);
47764727
dataChangedImpl(packageName, targets);
47774728
}
47784729

4779-
private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> targets) {
4730+
private void dataChangedImpl(String packageName, HashSet<String> targets) {
47804731
// Record that we need a backup pass for the caller. Since multiple callers
47814732
// may share a uid, we need to note all candidates within that uid and schedule
47824733
// a backup pass for each of them.
@@ -4790,27 +4741,23 @@ private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> target
47904741

47914742
synchronized (mQueueLock) {
47924743
// Note that this client has made data changes that need to be backed up
4793-
for (ApplicationInfo app : targets) {
4794-
// validate the caller-supplied package name against the known set of
4795-
// packages associated with this uid
4796-
if (app.packageName.equals(packageName)) {
4797-
// Add the caller to the set of pending backups. If there is
4798-
// one already there, then overwrite it, but no harm done.
4799-
BackupRequest req = new BackupRequest(packageName);
4800-
if (mPendingBackups.put(app.packageName, req) == null) {
4801-
if (DEBUG) Slog.d(TAG, "Now staging backup of " + packageName);
4802-
4803-
// Journal this request in case of crash. The put()
4804-
// operation returned null when this package was not already
4805-
// in the set; we want to avoid touching the disk redundantly.
4806-
writeToJournalLocked(packageName);
4744+
if (targets.contains(packageName)) {
4745+
// Add the caller to the set of pending backups. If there is
4746+
// one already there, then overwrite it, but no harm done.
4747+
BackupRequest req = new BackupRequest(packageName);
4748+
if (mPendingBackups.put(packageName, req) == null) {
4749+
if (DEBUG) Slog.d(TAG, "Now staging backup of " + packageName);
4750+
4751+
// Journal this request in case of crash. The put()
4752+
// operation returned null when this package was not already
4753+
// in the set; we want to avoid touching the disk redundantly.
4754+
writeToJournalLocked(packageName);
48074755

4808-
if (MORE_DEBUG) {
4809-
int numKeys = mPendingBackups.size();
4810-
Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
4811-
for (BackupRequest b : mPendingBackups.values()) {
4812-
Slog.d(TAG, " + " + b);
4813-
}
4756+
if (MORE_DEBUG) {
4757+
int numKeys = mPendingBackups.size();
4758+
Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
4759+
for (BackupRequest b : mPendingBackups.values()) {
4760+
Slog.d(TAG, " + " + b);
48144761
}
48154762
}
48164763
}
@@ -4819,7 +4766,7 @@ private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> target
48194766
}
48204767

48214768
// Note: packageName is currently unused, but may be in the future
4822-
private HashSet<ApplicationInfo> dataChangedTargets(String packageName) {
4769+
private HashSet<String> dataChangedTargets(String packageName) {
48234770
// If the caller does not hold the BACKUP permission, it can only request a
48244771
// backup of its own data.
48254772
if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
@@ -4831,11 +4778,11 @@ private HashSet<ApplicationInfo> dataChangedTargets(String packageName) {
48314778

48324779
// a caller with full permission can ask to back up any participating app
48334780
// !!! TODO: allow backup of ANY app?
4834-
HashSet<ApplicationInfo> targets = new HashSet<ApplicationInfo>();
4781+
HashSet<String> targets = new HashSet<String>();
48354782
synchronized (mBackupParticipants) {
48364783
int N = mBackupParticipants.size();
48374784
for (int i = 0; i < N; i++) {
4838-
HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
4785+
HashSet<String> s = mBackupParticipants.valueAt(i);
48394786
if (s != null) {
48404787
targets.addAll(s);
48414788
}
@@ -4862,7 +4809,7 @@ private void writeToJournalLocked(String str) {
48624809
// ----- IBackupManager binder interface -----
48634810

48644811
public void dataChanged(final String packageName) {
4865-
final HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
4812+
final HashSet<String> targets = dataChangedTargets(packageName);
48664813
if (targets == null) {
48674814
Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
48684815
+ " uid=" + Binder.getCallingUid());
@@ -4889,38 +4836,35 @@ public void clearBackupData(String packageName) {
48894836

48904837
// If the caller does not hold the BACKUP permission, it can only request a
48914838
// wipe of its own backed-up data.
4892-
HashSet<ApplicationInfo> apps;
4839+
HashSet<String> apps;
48934840
if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
48944841
Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
48954842
apps = mBackupParticipants.get(Binder.getCallingUid());
48964843
} else {
48974844
// a caller with full permission can ask to back up any participating app
48984845
// !!! TODO: allow data-clear of ANY app?
48994846
if (DEBUG) Slog.v(TAG, "Privileged caller, allowing clear of other apps");
4900-
apps = new HashSet<ApplicationInfo>();
4847+
apps = new HashSet<String>();
49014848
int N = mBackupParticipants.size();
49024849
for (int i = 0; i < N; i++) {
4903-
HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
4850+
HashSet<String> s = mBackupParticipants.valueAt(i);
49044851
if (s != null) {
49054852
apps.addAll(s);
49064853
}
49074854
}
49084855
}
49094856

4910-
// now find the given package in the set of candidate apps
4911-
for (ApplicationInfo app : apps) {
4912-
if (app.packageName.equals(packageName)) {
4913-
if (DEBUG) Slog.v(TAG, "Found the app - running clear process");
4914-
// found it; fire off the clear request
4915-
synchronized (mQueueLock) {
4916-
long oldId = Binder.clearCallingIdentity();
4917-
mWakelock.acquire();
4918-
Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR,
4919-
new ClearParams(getTransport(mCurrentTransport), info));
4920-
mBackupHandler.sendMessage(msg);
4921-
Binder.restoreCallingIdentity(oldId);
4922-
}
4923-
break;
4857+
// Is the given app an available participant?
4858+
if (apps.contains(packageName)) {
4859+
if (DEBUG) Slog.v(TAG, "Found the app - running clear process");
4860+
// found it; fire off the clear request
4861+
synchronized (mQueueLock) {
4862+
long oldId = Binder.clearCallingIdentity();
4863+
mWakelock.acquire();
4864+
Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR,
4865+
new ClearParams(getTransport(mCurrentTransport), info));
4866+
mBackupHandler.sendMessage(msg);
4867+
Binder.restoreCallingIdentity(oldId);
49244868
}
49254869
}
49264870
}
@@ -5838,9 +5782,9 @@ private void dumpInternal(PrintWriter pw) {
58385782
int uid = mBackupParticipants.keyAt(i);
58395783
pw.print(" uid: ");
58405784
pw.println(uid);
5841-
HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
5842-
for (ApplicationInfo app: participants) {
5843-
pw.println(" " + app.packageName);
5785+
HashSet<String> participants = mBackupParticipants.valueAt(i);
5786+
for (String app: participants) {
5787+
pw.println(" " + app);
58445788
}
58455789
}
58465790

0 commit comments

Comments
 (0)