diff --git a/res/values/strings.xml b/res/values/strings.xml
index c11ea3329ad..30ac7372e7e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6024,7 +6024,13 @@
%1$s will be able to read all notifications,
including personal information such as contact names and the text of messages you receive.
It will also be able to dismiss notifications or trigger action buttons they contain.
+ \n\nThis will also give the app the ability to turn Do Not Disturb on or off and change related settings.
+
+ If you turn off notification access for %1$s, Do Not Disturb access may also be turned off.
+
+ Turn off
+ Cancel
VR helper services
@@ -6870,6 +6876,8 @@
The app will be able to turn on/off Do Not Disturb and make changes to related settings.
+ Must stay turned on because notification access is on
+
Revoke access to Do Not Disturb for %1$s?
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
index 0111a38dfaf..d81bc0e7484 100644
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
@@ -16,8 +16,16 @@
package com.android.settings.notification;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.NotificationManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.pm.PackageManager;
+import android.os.AsyncTask;
+import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
@@ -30,6 +38,14 @@ public class NotificationAccessSettings extends ManagedServiceSettings {
private static final String TAG = NotificationAccessSettings.class.getSimpleName();
private static final Config CONFIG = getNotificationListenerConfig();
+ private NotificationManager mNm;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
private static Config getNotificationListenerConfig() {
final Config c = new Config();
c.tag = TAG;
@@ -60,4 +76,74 @@ public class NotificationAccessSettings extends ManagedServiceSettings {
public static int getEnabledListenersCount(Context context) {
return ServiceListing.getEnabledServicesCount(CONFIG, context);
}
+
+ protected boolean setEnabled(ComponentName service, String title, boolean enable) {
+ if (!enable) {
+ if (!mServiceListing.isEnabled(service)) {
+ return true; // already disabled
+ }
+ // show a friendly dialog
+ new FriendlyWarningDialogFragment()
+ .setServiceInfo(service, title)
+ .show(getFragmentManager(), "friendlydialog");
+ return false;
+ } else {
+ return super.setEnabled(service, title, enable);
+ }
+ }
+
+ private static void deleteRules(final Context context, final String pkg) {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ final NotificationManager mgr = context.getSystemService(NotificationManager.class);
+ mgr.removeAutomaticZenRules(pkg);
+ }
+ });
+ }
+
+ public class FriendlyWarningDialogFragment extends DialogFragment {
+ static final String KEY_COMPONENT = "c";
+ static final String KEY_LABEL = "l";
+
+ public FriendlyWarningDialogFragment setServiceInfo(ComponentName cn, String label) {
+ Bundle args = new Bundle();
+ args.putString(KEY_COMPONENT, cn.flattenToString());
+ args.putString(KEY_LABEL, label);
+ setArguments(args);
+ return this;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Bundle args = getArguments();
+ final String label = args.getString(KEY_LABEL);
+ final ComponentName cn = ComponentName.unflattenFromString(args
+ .getString(KEY_COMPONENT));
+
+ final String summary = getResources().getString(
+ R.string.notification_listener_disable_warning_summary, label);
+ return new AlertDialog.Builder(mContext)
+ .setMessage(summary)
+ .setCancelable(true)
+ .setPositiveButton(R.string.notification_listener_disable_warning_confirm,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ mServiceListing.setEnabled(cn, false);
+ if (!mNm.isNotificationPolicyAccessGrantedForPackage(
+ cn.getPackageName())) {
+ deleteRules(mContext, cn.getPackageName());
+ }
+ }
+ })
+ .setNegativeButton(R.string.notification_listener_disable_warning_cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // pass
+ }
+ })
+ .create();
+ }
+ }
}
diff --git a/src/com/android/settings/notification/ZenAccessSettings.java b/src/com/android/settings/notification/ZenAccessSettings.java
index 9ff2fedd498..638972e055a 100644
--- a/src/com/android/settings/notification/ZenAccessSettings.java
+++ b/src/com/android/settings/notification/ZenAccessSettings.java
@@ -21,6 +21,7 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.NotificationManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
@@ -32,6 +33,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.provider.Settings;
import android.provider.Settings.Secure;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
@@ -40,6 +42,8 @@ import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.ArraySet;
import android.view.View;
+import android.widget.Toast;
+
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -50,6 +54,7 @@ import java.util.List;
public class ZenAccessSettings extends EmptyTextSettings {
private final SettingObserver mObserver = new SettingObserver();
+ private static final String ENABLED_SERVICES_SEPARATOR = ":";
private Context mContext;
private PackageManager mPkgMan;
@@ -83,6 +88,9 @@ public class ZenAccessSettings extends EmptyTextSettings {
getContentResolver().registerContentObserver(
Secure.getUriFor(Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), false,
mObserver);
+ getContentResolver().registerContentObserver(
+ Secure.getUriFor(Secure.ENABLED_NOTIFICATION_LISTENERS), false,
+ mObserver);
}
@Override
@@ -96,7 +104,7 @@ public class ZenAccessSettings extends EmptyTextSettings {
screen.removeAll();
final ArrayList apps = new ArrayList<>();
final ArraySet requesting = mNoMan.getPackagesRequestingNotificationPolicyAccess();
- if (requesting != null && !requesting.isEmpty()) {
+ if (!requesting.isEmpty()) {
final List installed = mPkgMan.getInstalledApplications(0);
if (installed != null) {
for (ApplicationInfo app : installed) {
@@ -106,6 +114,8 @@ public class ZenAccessSettings extends EmptyTextSettings {
}
}
}
+ ArraySet autoApproved = getEnabledNotificationListeners();
+ requesting.addAll(autoApproved);
Collections.sort(apps, new PackageItemInfo.DisplayNameComparator(mPkgMan));
for (ApplicationInfo app : apps) {
final String pkg = app.packageName;
@@ -115,6 +125,10 @@ public class ZenAccessSettings extends EmptyTextSettings {
pref.setIcon(app.loadIcon(mPkgMan));
pref.setTitle(label);
pref.setChecked(hasAccess(pkg));
+ if (autoApproved.contains(pkg)) {
+ pref.setEnabled(false);
+ pref.setSummary(getString(R.string.zen_access_disabled_package_warning));
+ }
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
@@ -135,6 +149,22 @@ public class ZenAccessSettings extends EmptyTextSettings {
}
}
+ private ArraySet getEnabledNotificationListeners() {
+ ArraySet packages = new ArraySet<>();
+ String settingValue = Settings.Secure.getString(getContext().getContentResolver(),
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+ if (!TextUtils.isEmpty(settingValue)) {
+ String[] restored = settingValue.split(ENABLED_SERVICES_SEPARATOR);
+ for (int i = 0; i < restored.length; i++) {
+ ComponentName value = ComponentName.unflattenFromString(restored[i]);
+ if (null != value) {
+ packages.add(value.getPackageName());
+ }
+ }
+ }
+ return packages;
+ }
+
private boolean hasAccess(String pkg) {
return mNoMan.isNotificationPolicyAccessGrantedForPackage(pkg);
}
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 3cf28e1c74a..1fdba616a61 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -43,11 +43,10 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.utils.ManagedServiceSettings.Config;
-import com.android.settings.utils.ServiceListing;
+import com.android.settings.utils.ZenServiceListing;
import java.lang.ref.WeakReference;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
@@ -56,14 +55,14 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
static final Config CONFIG = getConditionProviderConfig();
private PackageManager mPm;
- private ServiceListing mServiceListing;
+ private ZenServiceListing mServiceListing;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.zen_mode_automation_settings);
mPm = mContext.getPackageManager();
- mServiceListing = new ServiceListing(mContext, CONFIG);
+ mServiceListing = new ZenServiceListing(mContext, CONFIG);
mServiceListing.reloadApprovedServices();
}
@@ -203,6 +202,7 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
final Config c = new Config();
c.tag = TAG;
c.setting = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES;
+ c.secondarySetting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
c.noun = "condition provider";
@@ -308,7 +308,7 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
: isEvent ? ZenModeEventRuleSettings.ACTION : "";
- ServiceInfo si = mServiceListing.findService(mContext, CONFIG, rule.getOwner());
+ ServiceInfo si = mServiceListing.findService(rule.getOwner());
ComponentName settingsActivity = getSettingsActivity(si);
setIntent(getRuleIntent(action, settingsActivity, mId));
setSelectable(settingsActivity != null || isSystemRule);
diff --git a/src/com/android/settings/notification/ZenRuleInfo.java b/src/com/android/settings/notification/ZenRuleInfo.java
index 2a06a08784d..2d7abf81bce 100644
--- a/src/com/android/settings/notification/ZenRuleInfo.java
+++ b/src/com/android/settings/notification/ZenRuleInfo.java
@@ -4,6 +4,31 @@ import android.content.ComponentName;
import android.net.Uri;
public class ZenRuleInfo {
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ZenRuleInfo that = (ZenRuleInfo) o;
+
+ if (isSystem != that.isSystem) return false;
+ if (ruleInstanceLimit != that.ruleInstanceLimit) return false;
+ if (packageName != null ? !packageName.equals(that.packageName) : that.packageName != null)
+ return false;
+ if (title != null ? !title.equals(that.title) : that.title != null) return false;
+ if (settingsAction != null ? !settingsAction.equals(
+ that.settingsAction) : that.settingsAction != null) return false;
+ if (configurationActivity != null ? !configurationActivity.equals(
+ that.configurationActivity) : that.configurationActivity != null) return false;
+ if (defaultConditionId != null ? !defaultConditionId.equals(
+ that.defaultConditionId) : that.defaultConditionId != null) return false;
+ if (serviceComponent != null ? !serviceComponent.equals(
+ that.serviceComponent) : that.serviceComponent != null) return false;
+ return packageLabel != null ? packageLabel.equals(
+ that.packageLabel) : that.packageLabel == null;
+
+ }
+
public String packageName;
public String title;
public String settingsAction;
diff --git a/src/com/android/settings/notification/ZenRuleSelectionDialog.java b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
index 05f42d8df01..9de9a603272 100644
--- a/src/com/android/settings/notification/ZenRuleSelectionDialog.java
+++ b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
@@ -27,6 +27,7 @@ import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.service.notification.ZenModeConfig;
+import android.util.ArraySet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -36,6 +37,7 @@ import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.utils.ServiceListing;
+import com.android.settings.utils.ZenServiceListing;
import java.lang.ref.WeakReference;
import java.text.Collator;
@@ -43,6 +45,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
public abstract class ZenRuleSelectionDialog {
private static final String TAG = "ZenRuleSelectionDialog";
@@ -53,9 +57,9 @@ public abstract class ZenRuleSelectionDialog {
private NotificationManager mNm;
private final AlertDialog mDialog;
private final LinearLayout mRuleContainer;
- private final ServiceListing mServiceListing;
+ private final ZenServiceListing mServiceListing;
- public ZenRuleSelectionDialog(Context context, ServiceListing serviceListing) {
+ public ZenRuleSelectionDialog(Context context, ZenServiceListing serviceListing) {
mContext = context;
mPm = context.getPackageManager();
mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -67,7 +71,7 @@ public abstract class ZenRuleSelectionDialog {
if (mServiceListing != null) {
bindType(defaultNewEvent());
bindType(defaultNewSchedule());
- mServiceListing.addCallback(mServiceListingCallback);
+ mServiceListing.addZenCallback(mServiceListingCallback);
mServiceListing.reloadApprovedServices();
}
mDialog = new AlertDialog.Builder(context)
@@ -77,7 +81,7 @@ public abstract class ZenRuleSelectionDialog {
@Override
public void onDismiss(DialogInterface dialog) {
if (mServiceListing != null) {
- mServiceListing.removeCallback(mServiceListingCallback);
+ mServiceListing.removeZenCallback(mServiceListingCallback);
}
}
})
@@ -152,24 +156,24 @@ public abstract class ZenRuleSelectionDialog {
return rt;
}
- private void bindExternalRules(List externalRuleTypes) {
- Collections.sort(externalRuleTypes, RULE_TYPE_COMPARATOR);
+ private void bindExternalRules(Set externalRuleTypes) {
for (ZenRuleInfo ri : externalRuleTypes) {
bindType(ri);
}
}
- private final ServiceListing.Callback mServiceListingCallback = new ServiceListing.Callback() {
+ private final ZenServiceListing.Callback mServiceListingCallback = new
+ ZenServiceListing.Callback() {
@Override
- public void onServicesReloaded(List services) {
+ public void onServicesReloaded(Set services) {
if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
- List externalRuleTypes = new ArrayList<>();
- for (int i = 0; i < services.size(); i++) {
- final ZenRuleInfo ri = ZenModeAutomationSettings.getRuleInfo(mPm, services.get(i));
+ Set externalRuleTypes = new TreeSet<>(RULE_TYPE_COMPARATOR);
+ for (ServiceInfo serviceInfo : services) {
+ final ZenRuleInfo ri = ZenModeAutomationSettings.getRuleInfo(mPm, serviceInfo);
if (ri != null && ri.configurationActivity != null
&& mNm.isNotificationPolicyAccessGrantedForPackage(ri.packageName)
&& (ri.ruleInstanceLimit <= 0 || ri.ruleInstanceLimit
- >= (mNm.getRuleInstanceCount(services.get(i).getComponentName()) + 1))) {
+ >= (mNm.getRuleInstanceCount(serviceInfo.getComponentName()) + 1))) {
externalRuleTypes.add(ri);
}
}
diff --git a/src/com/android/settings/utils/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java
index e198955baaa..da4798e09a8 100644
--- a/src/com/android/settings/utils/ManagedServiceSettings.java
+++ b/src/com/android/settings/utils/ManagedServiceSettings.java
@@ -42,9 +42,9 @@ import java.util.List;
public abstract class ManagedServiceSettings extends EmptyTextSettings {
private final Config mConfig;
- private Context mContext;
+ protected Context mContext;
private PackageManager mPM;
- private ServiceListing mServiceListing;
+ protected ServiceListing mServiceListing;
private TextView mEmpty;
abstract protected Config getConfig();
@@ -111,7 +111,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
}
}
- private boolean setEnabled(ComponentName service, String title, boolean enable) {
+ protected boolean setEnabled(ComponentName service, String title, boolean enable) {
if (!enable) {
// the simple version: disabling
mServiceListing.setEnabled(service, false);
@@ -173,6 +173,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
public static class Config {
public String tag;
public String setting;
+ public String secondarySetting;
public String intentAction;
public String permission;
public String noun;
diff --git a/src/com/android/settings/utils/ServiceListing.java b/src/com/android/settings/utils/ServiceListing.java
index dfca5a3d65c..6a5fa103531 100644
--- a/src/com/android/settings/utils/ServiceListing.java
+++ b/src/com/android/settings/utils/ServiceListing.java
@@ -30,6 +30,7 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.Slog;
import com.android.settings.utils.ManagedServiceSettings.Config;
@@ -46,7 +47,6 @@ public class ServiceListing {
private final HashSet mEnabledServices = new HashSet();
private final List mServices = new ArrayList();
private final List mCallbacks = new ArrayList();
- private final List mApprovedServices = new ArrayList();
private boolean mListening;
@@ -95,18 +95,7 @@ public class ServiceListing {
return getServices(c, null, pm);
}
- public ServiceInfo findService(Context context, Config config, final ComponentName cn) {
- final ServiceListing listing = new ServiceListing(context, config);
- for (ServiceInfo service : mApprovedServices) {
- final ComponentName serviceCN = new ComponentName(service.packageName, service.name);
- if (serviceCN.equals(cn)) {
- return service;
- }
- }
- return null;
- }
-
- private static int getServices(Config c, List list, PackageManager pm) {
+ protected static int getServices(Config c, List list, PackageManager pm) {
int services = 0;
if (list != null) {
list.clear();
@@ -174,26 +163,6 @@ public class ServiceListing {
return mServices;
}
- public void reloadApprovedServices() {
- mApprovedServices.clear();
- final String flat = Settings.Secure.getString(mContentResolver, mConfig.setting);
- if (flat != null && !"".equals(flat)) {
- final List names = Arrays.asList(flat.split(":"));
- List services = new ArrayList<>();
- getServices(mConfig, services, mContext.getPackageManager());
- for (ServiceInfo service : services) {
- final ComponentName componentName = service.getComponentName();
- String flatCn = service.getComponentName().flattenToString();
- if (names.contains(flatCn) || names.contains(componentName.getPackageName())) {
- mApprovedServices.add(service);
- }
- }
- for (Callback callback : mCallbacks) {
- callback.onServicesReloaded(mApprovedServices);
- }
- }
- }
-
public boolean isEnabled(ComponentName cn) {
return mEnabledServices.contains(cn);
}
diff --git a/src/com/android/settings/utils/ZenServiceListing.java b/src/com/android/settings/utils/ZenServiceListing.java
new file mode 100644
index 00000000000..167b066302d
--- /dev/null
+++ b/src/com/android/settings/utils/ZenServiceListing.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.utils;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+public class ZenServiceListing {
+
+ private final ContentResolver mContentResolver;
+ private final Context mContext;
+ private final ManagedServiceSettings.Config mConfig;
+ private final Set mApprovedServices = new ArraySet();
+ private final List mZenCallbacks = new ArrayList<>();
+
+ public ZenServiceListing(Context context, ManagedServiceSettings.Config config) {
+ mContext = context;
+ mConfig = config;
+ mContentResolver = context.getContentResolver();
+ }
+
+ public ServiceInfo findService(final ComponentName cn) {
+ for (ServiceInfo service : mApprovedServices) {
+ final ComponentName serviceCN = new ComponentName(service.packageName, service.name);
+ if (serviceCN.equals(cn)) {
+ return service;
+ }
+ }
+ return null;
+ }
+
+ public void addZenCallback(Callback callback) {
+ mZenCallbacks.add(callback);
+ }
+
+ public void removeZenCallback(Callback callback) {
+ mZenCallbacks.remove(callback);
+ }
+
+ public void reloadApprovedServices() {
+ mApprovedServices.clear();
+ String[] settings = {mConfig.setting, mConfig.secondarySetting};
+
+ for (String setting : settings) {
+ if (!TextUtils.isEmpty(setting)) {
+ final String flat = Settings.Secure.getString(mContentResolver, setting);
+ if (!TextUtils.isEmpty(flat)) {
+ final List names = Arrays.asList(flat.split(":"));
+ List services = new ArrayList<>();
+ getServices(mConfig, services, mContext.getPackageManager());
+ for (ServiceInfo service : services) {
+ if (matchesApprovedPackage(names, service.getComponentName())) {
+ mApprovedServices.add(service);
+ }
+ }
+ }
+ }
+ }
+ if (!mApprovedServices.isEmpty()) {
+ for (Callback callback : mZenCallbacks) {
+ callback.onServicesReloaded(mApprovedServices);
+ }
+ }
+ }
+
+ // Setting could contain: the component name of the condition provider, the package name of
+ // the condition provider, the component name of the notification listener.
+ private boolean matchesApprovedPackage(List approved, ComponentName serviceOwner) {
+ String flatCn = serviceOwner.flattenToString();
+ if (approved.contains(flatCn) || approved.contains(serviceOwner.getPackageName())) {
+ return true;
+ }
+ for (String entry : approved) {
+ if (!TextUtils.isEmpty(entry)) {
+ ComponentName approvedComponent = ComponentName.unflattenFromString(entry);
+ if (approvedComponent != null && approvedComponent.getPackageName().equals(
+ serviceOwner.getPackageName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static int getServices(ManagedServiceSettings.Config c, List list,
+ PackageManager pm) {
+ int services = 0;
+ if (list != null) {
+ list.clear();
+ }
+ final int user = ActivityManager.getCurrentUser();
+
+ List installedServices = pm.queryIntentServicesAsUser(
+ new Intent(c.intentAction),
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+ user);
+
+ for (int i = 0, count = installedServices.size(); i < count; i++) {
+ ResolveInfo resolveInfo = installedServices.get(i);
+ ServiceInfo info = resolveInfo.serviceInfo;
+
+ if (!c.permission.equals(info.permission)) {
+ Slog.w(c.tag, "Skipping " + c.noun + " service "
+ + info.packageName + "/" + info.name
+ + ": it does not require the permission "
+ + c.permission);
+ continue;
+ }
+ if (list != null) {
+ list.add(info);
+ }
+ services++;
+ }
+ return services;
+ }
+
+ public interface Callback {
+ void onServicesReloaded(Set services);
+ }
+}