diff options
author | Chris Wren <cwren@android.com> | 2013-05-15 14:50:28 -0400 |
---|---|---|
committer | Chris Wren <cwren@android.com> | 2013-05-17 16:02:53 -0400 |
commit | ae9bb5737c656f48b889f37f5d23b251db8f0caf (patch) | |
tree | 82176f9132d903f81f46e192052d387313e9d8ac /services/java/com/android/server/NotificationManagerService.java | |
parent | c037282c1ca0d7589168c73f1cf8b19ecc3ffca4 (diff) |
disable notification listeners on uninstall
Bug: 8979640
Change-Id: I9f1d118e5ce210b829476e0971f3d55fc778c227
Diffstat (limited to 'services/java/com/android/server/NotificationManagerService.java')
-rw-r--r-- | services/java/com/android/server/NotificationManagerService.java | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index f9b6eba68b60..903bc0bfc526 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -40,6 +40,8 @@ import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.database.ContentObserver; @@ -88,7 +90,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.NoSuchElementException; +import java.util.Set; import libcore.io.IoUtils; @@ -533,6 +537,60 @@ public class NotificationManagerService extends INotificationManager.Stub } /** + * Remove notification access for any services that no longer exist. + */ + void disableNonexistentListeners() { + int currentUser = ActivityManager.getCurrentUser(); + String flatIn = Settings.Secure.getStringForUser( + mContext.getContentResolver(), + Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, + currentUser); + if (!TextUtils.isEmpty(flatIn)) { + if (DBG) Slog.v(TAG, "flat before: " + flatIn); + PackageManager pm = mContext.getPackageManager(); + List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser( + new Intent(NotificationListenerService.SERVICE_INTERFACE), + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, + currentUser); + + Set<ComponentName> installed = new HashSet<ComponentName>(); + for (int i = 0, count = installedServices.size(); i < count; i++) { + ResolveInfo resolveInfo = installedServices.get(i); + ServiceInfo info = resolveInfo.serviceInfo; + + if (!android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE.equals( + info.permission)) { + Slog.w(TAG, "Skipping notification listener service " + + info.packageName + "/" + info.name + + ": it does not require the permission " + + android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); + continue; + } + installed.add(new ComponentName(info.packageName, info.name)); + } + + String flatOut = ""; + if (!installed.isEmpty()) { + String[] enabled = flatIn.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR); + ArrayList<String> remaining = new ArrayList<String>(enabled.length); + for (int i = 0; i < enabled.length; i++) { + ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]); + if (installed.contains(enabledComponent)) { + remaining.add(enabled[i]); + } + } + flatOut = TextUtils.join(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR, remaining); + } + if (DBG) Slog.v(TAG, "flat after: " + flatOut); + if (!flatIn.equals(flatOut)) { + Settings.Secure.putStringForUser(mContext.getContentResolver(), + Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, + flatOut, currentUser); + } + } + } + + /** * Called whenever packages change, the user switches, or ENABLED_NOTIFICATION_LISTENERS * is altered. (For example in response to USER_SWITCHED in our broadcast receiver) */ @@ -1073,15 +1131,19 @@ public class NotificationManagerService extends INotificationManager.Stub String action = intent.getAction(); boolean queryRestart = false; + boolean queryRemove = false; boolean packageChanged = false; if (action.equals(Intent.ACTION_PACKAGE_ADDED) - || action.equals(Intent.ACTION_PACKAGE_REMOVED) + || (queryRemove=action.equals(Intent.ACTION_PACKAGE_REMOVED)) || action.equals(Intent.ACTION_PACKAGE_RESTARTED) || (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED)) || (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART)) || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { String pkgList[] = null; + boolean queryReplace = queryRemove && + intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + if (DBG) Slog.i(TAG, "queryReplace=" + queryReplace); if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); } else if (queryRestart) { @@ -1119,6 +1181,10 @@ public class NotificationManagerService extends INotificationManager.Stub } if (anyListenersInvolved) { + // if we're not replacing a package, clean up orphaned bits + if (!queryReplace) { + disableNonexistentListeners(); + } // make sure we're still bound to any of our // listeners who may have just upgraded rebindListenerServices(); |