@@ -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