Purge an app's scheduled jobs when the whole package is disabled
Bug 28979894
Change-Id: If8a99489eaaa219274289fdf2e90be8bdecb3bfa
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 491ee18..1b8eccb 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -16,6 +16,9 @@
package com.android.server.job;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -41,6 +44,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
@@ -217,7 +221,41 @@
if (DEBUG) {
Slog.d(TAG, "Receieved: " + intent.getAction());
}
- if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+ if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
+ // Purge the app's jobs if the whole package was just disabled. When this is
+ // the case the component name will be a bare package name.
+ final String pkgName = getPackageName(intent);
+ final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ if (pkgName != null && pkgUid != -1) {
+ final String[] changedComponents = intent.getStringArrayExtra(
+ Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ if (changedComponents != null) {
+ for (String component : changedComponents) {
+ if (component.equals(pkgName)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Package state change: " + pkgName);
+ }
+ try {
+ final int userId = UserHandle.getUserId(pkgUid);
+ IPackageManager pm = AppGlobals.getPackageManager();
+ final int state = pm.getApplicationEnabledSetting(pkgName, userId);
+ if (state == COMPONENT_ENABLED_STATE_DISABLED
+ || state == COMPONENT_ENABLED_STATE_DISABLED_USER) {
+ if (DEBUG) {
+ Slog.d(TAG, "Removing jobs for package " + pkgName
+ + " in user " + userId);
+ }
+ cancelJobsForUid(pkgUid, true);
+ }
+ } catch (RemoteException e) { /* cannot happen */ }
+ break;
+ }
+ }
+ }
+ } else {
+ Slog.w(TAG, "PACKAGE_CHANGED for " + pkgName + " / uid " + pkgUid);
+ }
+ } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
// If this is an outright uninstall rather than the first half of an
// app update sequence, cancel the jobs associated with the app.
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
@@ -237,6 +275,12 @@
}
};
+ private String getPackageName(Intent intent) {
+ Uri uri = intent.getData();
+ String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+ return pkg;
+ }
+
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
updateUidState(uid, procState);
@@ -520,7 +564,9 @@
public void onBootPhase(int phase) {
if (PHASE_SYSTEM_SERVICES_READY == phase) {
// Register br for package removals and user removals.
- final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, filter, null, null);