summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Annie Meng <anniemeng@google.com> 2019-01-09 17:52:22 +0000
committer Annie Meng <anniemeng@google.com> 2019-01-10 14:25:47 +0000
commit4f98512cc5eb420ef55ed32b73e04632034d98cd (patch)
tree85c1c78e4e24fb05a5062160920c3dccd1ee4e5e
parente714a7eaa9e45485be9f29aa58efe41ffa313839 (diff)
[Multi-user] Make package changes receiver per-user
Makes the BroadcastReceiver that receives changes to installed packages and sdcards tied to a specific user. Bug: 121198607 Test: 1) atest RunBackupFrameworksServicesRoboTests 2) Manual testing with user 0 and 11: - User started -> receiver registered for correct user; - Package changed -> correct receiver; - Package added -> correct receiver, updates bookkeeping for correct user; - Package removed -> correct receiver, updates bookkeeping for correct user; Change-Id: I68c034da6ec775a4d0489a2d09fc32854dcf11dc
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java105
-rw-r--r--services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java33
2 files changed, 91 insertions, 47 deletions
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index b01117c438f0..d51eac386083 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -830,19 +830,29 @@ public class UserBackupManagerService {
mFullBackupQueue = readFullBackupSchedule();
}
- // Register for broadcasts about package install, etc., so we can
- // update the provider list.
+ // Register for broadcasts about package changes.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
- mContext.registerReceiver(mBroadcastReceiver, filter);
+ mContext.registerReceiverAsUser(
+ mBroadcastReceiver,
+ UserHandle.of(mUserId),
+ filter,
+ /* broadcastPermission */ null,
+ /* scheduler */ null);
+
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(mBroadcastReceiver, sdFilter);
+ mContext.registerReceiverAsUser(
+ mBroadcastReceiver,
+ UserHandle.of(mUserId),
+ sdFilter,
+ /* broadcastPermission */ null,
+ /* scheduler */ null);
}
private ArrayList<FullBackupEntry> readFullBackupSchedule() {
@@ -1107,17 +1117,23 @@ public class UserBackupManagerService {
}
}
- // ----- Track installation/removal of packages -----
+ /**
+ * A {@link BroadcastReceiver} tracking changes to packages and sd cards in order to update our
+ * internal bookkeeping.
+ */
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
- if (MORE_DEBUG) Slog.d(TAG, "Received broadcast " + intent);
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "Received broadcast " + intent);
+ }
String action = intent.getAction();
boolean replacing = false;
boolean added = false;
boolean changed = false;
Bundle extras = intent.getExtras();
- String[] pkgList = null;
+ String[] packageList = null;
+
if (Intent.ACTION_PACKAGE_ADDED.equals(action)
|| Intent.ACTION_PACKAGE_REMOVED.equals(action)
|| Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
@@ -1125,69 +1141,70 @@ public class UserBackupManagerService {
if (uri == null) {
return;
}
- final String pkgName = uri.getSchemeSpecificPart();
- if (pkgName != null) {
- pkgList = new String[]{pkgName};
+
+ String packageName = uri.getSchemeSpecificPart();
+ if (packageName != null) {
+ packageList = new String[]{packageName};
}
- changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
- // At package-changed we only care about looking at new transport states
+ changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
if (changed) {
- final String[] components =
+ // Look at new transport states for package changed events.
+ String[] components =
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
if (MORE_DEBUG) {
- Slog.i(TAG, "Package " + pkgName + " changed; rechecking");
+ Slog.i(TAG, "Package " + packageName + " changed");
for (int i = 0; i < components.length; i++) {
Slog.i(TAG, " * " + components[i]);
}
}
mBackupHandler.post(
- () -> mTransportManager.onPackageChanged(pkgName, components));
- return; // nothing more to do in the PACKAGE_CHANGED case
+ () -> mTransportManager.onPackageChanged(packageName, components));
+ return;
}
added = Intent.ACTION_PACKAGE_ADDED.equals(action);
replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
added = true;
- pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ packageList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
added = false;
- pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ packageList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
- if (pkgList == null || pkgList.length == 0) {
+ if (packageList == null || packageList.length == 0) {
return;
}
- final int uid = extras.getInt(Intent.EXTRA_UID);
+ int uid = extras.getInt(Intent.EXTRA_UID);
if (added) {
synchronized (mBackupParticipants) {
if (replacing) {
- // This is the package-replaced case; we just remove the entry
- // under the old uid and fall through to re-add. If an app
- // just added key/value backup participation, this picks it up
- // as a known participant.
- removePackageParticipantsLocked(pkgList, uid);
+ // Remove the entry under the old uid and fall through to re-add. If an app
+ // just opted into key/value backup, add it as a known participant.
+ removePackageParticipantsLocked(packageList, uid);
}
- addPackageParticipantsLocked(pkgList);
+ addPackageParticipantsLocked(packageList);
}
- // If they're full-backup candidates, add them there instead
- final long now = System.currentTimeMillis();
- for (final String packageName : pkgList) {
+
+ long now = System.currentTimeMillis();
+ for (String packageName : packageList) {
try {
- PackageInfo app = mPackageManager.getPackageInfo(packageName, 0);
+ PackageInfo app =
+ mPackageManager.getPackageInfoAsUser(
+ packageName, /* flags */ 0, mUserId);
if (AppBackupUtils.appGetsFullBackup(app)
&& AppBackupUtils.appIsEligibleForBackup(
app.applicationInfo, mPackageManager)) {
enqueueFullBackup(packageName, now);
scheduleNextFullBackupJob(0);
} else {
- // The app might have just transitioned out of full-data into
- // doing key/value backups, or might have just disabled backups
- // entirely. Make sure it is no longer in the full-data queue.
+ // The app might have just transitioned out of full-data into doing
+ // key/value backups, or might have just disabled backups entirely. Make
+ // sure it is no longer in the full-data queue.
synchronized (mQueueLock) {
dequeueFullBackupLocked(packageName);
}
@@ -1196,32 +1213,28 @@ public class UserBackupManagerService {
mBackupHandler.post(
() -> mTransportManager.onPackageAdded(packageName));
-
} catch (NameNotFoundException e) {
- // doesn't really exist; ignore it
if (DEBUG) {
Slog.w(TAG, "Can't resolve new app " + packageName);
}
}
}
- // Whenever a package is added or updated we need to update
- // the package metadata bookkeeping.
+ // Whenever a package is added or updated we need to update the package metadata
+ // bookkeeping.
dataChangedImpl(PACKAGE_MANAGER_SENTINEL);
} else {
- if (replacing) {
- // The package is being updated. We'll receive a PACKAGE_ADDED shortly.
- } else {
- // Outright removal. In the full-data case, the app will be dropped
- // from the queue when its (now obsolete) name comes up again for
- // backup.
+ if (!replacing) {
+ // Outright removal. In the full-data case, the app will be dropped from the
+ // queue when its (now obsolete) name comes up again for backup.
synchronized (mBackupParticipants) {
- removePackageParticipantsLocked(pkgList, uid);
+ removePackageParticipantsLocked(packageList, uid);
}
}
- for (final String pkgName : pkgList) {
+
+ for (String packageName : packageList) {
mBackupHandler.post(
- () -> mTransportManager.onPackageRemoved(pkgName));
+ () -> mTransportManager.onPackageRemoved(packageName));
}
}
}
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 5e84ab0d66f7..7dac79599ac6 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -71,6 +71,7 @@ import static java.util.stream.Collectors.toList;
import android.annotation.Nullable;
import android.app.Application;
+import android.app.ApplicationPackageManager;
import android.app.IBackupAgent;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
@@ -134,6 +135,8 @@ import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.shadows.ShadowPackageManager;
import org.robolectric.shadows.ShadowQueuedWork;
@@ -157,6 +160,7 @@ import java.util.stream.Stream;
@Config(
shadows = {
FrameworkShadowLooper.class,
+ KeyValueBackupTaskTest.ShadowApplicationPackageManager.class,
ShadowBackupDataInput.class,
ShadowBackupDataOutput.class,
ShadowEventLog.class,
@@ -244,6 +248,7 @@ public class KeyValueBackupTaskTest {
@After
public void tearDown() throws Exception {
ShadowBackupDataInput.reset();
+ ShadowApplicationPackageManager.reset();
}
@Test
@@ -2435,7 +2440,8 @@ public class KeyValueBackupTaskTest {
mPackageManager.setApplicationEnabledSetting(
packageData.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
PackageInfo packageInfo = getPackageInfo(packageData);
- mShadowPackageManager.addPackage(packageInfo);
+ mShadowPackageManager.installPackage(packageInfo);
+ ShadowApplicationPackageManager.setPackageInfo(packageInfo);
mContext.sendBroadcast(getPackageAddedIntent(packageData));
// Run the backup looper because on the receiver we post MSG_SCHEDULE_BACKUP_PACKAGE
mShadowBackupLooper.runToEndOfTasks();
@@ -2848,4 +2854,29 @@ public class KeyValueBackupTaskTest {
throw mException;
}
}
+
+ /**
+ * Extends {@link org.robolectric.shadows.ShadowApplicationPackageManager} to return the correct
+ * package in user-specific invocations.
+ */
+ @Implements(value = ApplicationPackageManager.class)
+ public static class ShadowApplicationPackageManager
+ extends org.robolectric.shadows.ShadowApplicationPackageManager {
+ private static PackageInfo sPackageInfo;
+
+ static void setPackageInfo(PackageInfo packageInfo) {
+ sPackageInfo = packageInfo;
+ }
+
+ @Override
+ protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) {
+ return sPackageInfo;
+ }
+
+ /** Clear {@link #sPackageInfo}. */
+ @Resetter
+ public static void reset() {
+ sPackageInfo = null;
+ }
+ }
}