OSDN Git Service

Optionally append managed service approvals
[android-x86/frameworks-base.git] / services / core / java / com / android / server / notification / ManagedServices.java
index dc85dd7..5251c78 100644 (file)
@@ -19,10 +19,12 @@ package com.android.server.notification;
 import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
 import static android.content.Context.BIND_AUTO_CREATE;
 import static android.content.Context.BIND_FOREGROUND_SERVICE;
+import static android.content.Context.DEVICE_POLICY_SERVICE;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -31,6 +33,7 @@ import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -38,11 +41,13 @@ import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IInterface;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -82,12 +87,13 @@ abstract public class ManagedServices {
     protected final Object mMutex;
     private final UserProfiles mUserProfiles;
     private final SettingsObserver mSettingsObserver;
+    private final IPackageManager mPm;
     private final Config mConfig;
     private ArraySet<String> mRestored;
 
     // contains connections to all connected services, including app services
     // and system services
-    protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
+    private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
     // things that will be put into mServices as soon as they're ready
     private final ArrayList<String> mServicesBinding = new ArrayList<String>();
     // lists the component names of all enabled (and therefore potentially connected)
@@ -114,6 +120,7 @@ abstract public class ManagedServices {
         mContext = context;
         mMutex = mutex;
         mUserProfiles = userProfiles;
+        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
         mConfig = getConfig();
         mSettingsObserver = new SettingsObserver(handler);
 
@@ -132,6 +139,19 @@ abstract public class ManagedServices {
                         || Objects.equals(element, mConfig.secondarySettingName)) {
                     String prevValue = intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
                     String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
+                    int restoredFromSdkInt = intent.getIntExtra(
+                            Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, 0);
+                    if (restoredFromSdkInt < Build.VERSION_CODES.O) {
+                        // automatic system grants were added in O, so append the approved apps
+                        // rather than wiping out the setting
+                        if (!TextUtils.isEmpty(prevValue)) {
+                            if (!TextUtils.isEmpty(newValue)) {
+                                newValue = newValue + ENABLED_SERVICES_SEPARATOR + prevValue;
+                            } else {
+                                newValue = prevValue;
+                            }
+                        }
+                    }
                     settingRestored(element, prevValue, newValue, getSendingUserId());
                 }
             }
@@ -150,6 +170,13 @@ abstract public class ManagedServices {
 
     abstract protected void onServiceAdded(ManagedServiceInfo info);
 
+    protected List<ManagedServiceInfo> getServices() {
+        synchronized (mMutex) {
+            List<ManagedServiceInfo> services = new ArrayList<>(mServices);
+            return services;
+        }
+    }
+
     protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
 
     private ManagedServiceInfo newServiceInfo(IInterface service,
@@ -207,7 +234,9 @@ abstract public class ManagedServices {
                         restoredSettingName(element),
                         newValue,
                         userid);
-                updateSettingsAccordingToInstalledServices(element, userid);
+                if (mConfig.secureSettingName.equals(element)) {
+                    updateSettingsAccordingToInstalledServices(element, userid);
+                }
                 rebuildRestoredPackages();
             }
         }
@@ -217,8 +246,8 @@ abstract public class ManagedServices {
         return mEnabledServicesPackageNames.contains(pkg);
     }
 
-    public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
-        if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
+    public void onPackagesChanged(boolean removingPackage, String[] pkgList) {
+        if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
                 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
                 + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
         boolean anyServicesInvolved = false;
@@ -234,7 +263,7 @@ abstract public class ManagedServices {
 
         if (anyServicesInvolved) {
             // if we're not replacing a package, clean up orphaned bits
-            if (!queryReplace) {
+            if (removingPackage) {
                 updateSettingsAccordingToInstalledServices();
                 rebuildRestoredPackages();
             }
@@ -345,7 +374,6 @@ abstract public class ManagedServices {
 
     private void rebuildRestoredPackages() {
         mRestoredPackages.clear();
-        mSnoozingForCurrentProfiles.clear();
         String secureSettingName = restoredSettingName(mConfig.secureSettingName);
         String secondarySettingName = mConfig.secondarySettingName == null
                 ? null : restoredSettingName(mConfig.secondarySettingName);
@@ -575,8 +603,21 @@ abstract public class ManagedServices {
         for (int i = 0; i < nUserIds; ++i) {
             final Set<ComponentName> add = toAdd.get(userIds[i]);
             for (ComponentName component : add) {
-                Slog.v(TAG, "enabling " + getCaption() + " for " + userIds[i] + ": " + component);
-                registerService(component, userIds[i]);
+                try {
+                    ServiceInfo info = mPm.getServiceInfo(component,
+                            PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userIds[i]);
+                    if (info == null || !mConfig.bindPermission.equals(info.permission)) {
+                        Slog.w(TAG, "Skipping " + getCaption() + " service " + component
+                                + ": it does not require the permission " + mConfig.bindPermission);
+                        continue;
+                    }
+                    Slog.v(TAG,
+                            "enabling " + getCaption() + " for " + userIds[i] + ": " + component);
+                    registerService(component, userIds[i]);
+                } catch (RemoteException e) {
+                    e.rethrowFromSystemServer();
+                }
             }
         }
 
@@ -872,7 +913,9 @@ abstract public class ManagedServices {
             if (this.userid == UserHandle.USER_ALL) return true;
             if (this.isSystem) return true;
             if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
-            return supportsProfiles() && mUserProfiles.isCurrentProfile(nid);
+            return supportsProfiles()
+                    && mUserProfiles.isCurrentProfile(nid)
+                    && isPermittedForProfile(nid);
         }
 
         public boolean supportsProfiles() {
@@ -883,7 +926,7 @@ abstract public class ManagedServices {
         public void binderDied() {
             if (DEBUG) Slog.d(TAG, "binderDied");
             // Remove the service, but don't unbind from the service. The system will bring the
-            // service back up, and the onServiceConnected handler will readd the service with the
+            // service back up, and the onServiceConnected handler will read the service with the
             // new binding. If this isn't a bound service, and is just a registered
             // service, just removing it from the list is all we need to do anyway.
             removeServiceImpl(this.service, this.userid);
@@ -895,6 +938,26 @@ abstract public class ManagedServices {
             if (this.connection == null) return false;
             return mEnabledServicesForCurrentProfiles.contains(this.component);
         }
+
+        /**
+         * Returns true if this service is allowed to receive events for the given userId. A
+         * managed profile owner can disallow non-system services running outside of the profile
+         * from receiving events from the profile.
+         */
+        public boolean isPermittedForProfile(int userId) {
+            if (!mUserProfiles.isManagedProfile(userId)) {
+                return true;
+            }
+            DevicePolicyManager dpm =
+                    (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                return dpm.isNotificationListenerServicePermitted(
+                        component.getPackageName(), userId);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
     }
 
     /** convenience method for looking in mEnabledServicesForCurrentProfiles */
@@ -936,6 +999,13 @@ abstract public class ManagedServices {
                 return mCurrentProfiles.get(userId) != null;
             }
         }
+
+        public boolean isManagedProfile(int userId) {
+            synchronized (mCurrentProfiles) {
+                UserInfo user = mCurrentProfiles.get(userId);
+                return user != null && user.isManagedProfile();
+            }
+        }
     }
 
     public static class Config {