Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 961797ca authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert "Modify to ensure that ManagedServices supports concurrent...

Merge "Revert "Modify to ensure that ManagedServices supports concurrent multi-user environments"" into main
parents b3a7a167 38c5e7ab
Loading
Loading
Loading
Loading
+38 −252
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@ import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.service.notification.NotificationListenerService.META_DATA_DEFAULT_AUTOBIND;

import static com.android.server.notification.Flags.FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER;
import static com.android.server.notification.Flags.managedServicesConcurrentMultiuser;
import static com.android.server.notification.NotificationManagerService.privateSpaceFlagsEnabled;

import android.annotation.FlaggedApi;
@@ -77,9 +75,7 @@ import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.TriPredicate;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerService.DumpFilter;
import com.android.server.pm.UserManagerInternal;
import com.android.server.utils.TimingsTraceAndSlog;

import org.xmlpull.v1.XmlPullParser;
@@ -138,7 +134,6 @@ abstract public class ManagedServices {
    private final UserProfiles mUserProfiles;
    protected final IPackageManager mPm;
    protected final UserManager mUm;
    protected final UserManagerInternal mUmInternal;
    private final Config mConfig;
    private final Handler mHandler = new Handler(Looper.getMainLooper());

@@ -162,17 +157,12 @@ abstract public class ManagedServices {
    protected final ArraySet<String> mDefaultPackages = new ArraySet<>();

    // lists the component names of all enabled (and therefore potentially connected)
    // app services for each user. This is intended to support a concurrent multi-user environment.
    // key value is the resolved userId.
    // app services for current profiles.
    @GuardedBy("mMutex")
    private final SparseArray<ArraySet<ComponentName>> mEnabledServicesByUser =
            new SparseArray<>();
    // Just the packages from mEnabledServicesByUser
    // This is intended to support a concurrent multi-user environment.
    // key value is the resolved userId.
    private final ArraySet<ComponentName> mEnabledServicesForCurrentProfiles = new ArraySet<>();
    // Just the packages from mEnabledServicesForCurrentProfiles
    @GuardedBy("mMutex")
    private final SparseArray<ArraySet<String>> mEnabledServicesPackageNamesByUser =
            new SparseArray<>();
    private final ArraySet<String> mEnabledServicesPackageNames = new ArraySet<>();
    // Per user id, list of enabled packages that have nevertheless asked not to be run
    @GuardedBy("mSnoozing")
    private final SparseSetArray<ComponentName> mSnoozing = new SparseSetArray<>();
@@ -205,7 +195,6 @@ abstract public class ManagedServices {
        mConfig = getConfig();
        mApprovalLevel = APPROVAL_BY_COMPONENT;
        mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mUmInternal = LocalServices.getService(UserManagerInternal.class);
    }

    abstract protected Config getConfig();
@@ -394,31 +383,12 @@ abstract public class ManagedServices {
        }

        synchronized (mMutex) {
            if (managedServicesConcurrentMultiuser()) {
                for (int i = 0; i < mEnabledServicesByUser.size(); i++) {
                    final int userId = mEnabledServicesByUser.keyAt(i);
                    final ArraySet<ComponentName> componentNames =
                            mEnabledServicesByUser.get(userId);
                    String userString = userId == UserHandle.USER_CURRENT
                            ? "current profiles" : "user " + Integer.toString(userId);
                    pw.println("    All " + getCaption() + "s (" + componentNames.size()
                            + ") enabled for " +  userString + ":");
                    for (ComponentName cmpt : componentNames) {
                        if (filter != null && !filter.matches(cmpt)) continue;
                        pw.println("      " + cmpt);
                    }
                }
            } else {
                final ArraySet<ComponentName> enabledServicesForCurrentProfiles =
                        mEnabledServicesByUser.get(UserHandle.USER_CURRENT);
                pw.println("    All " + getCaption() + "s ("
                        + enabledServicesForCurrentProfiles.size()
            pw.println("    All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size()
                    + ") enabled for current profiles:");
                for (ComponentName cmpt : enabledServicesForCurrentProfiles) {
            for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
                if (filter != null && !filter.matches(cmpt)) continue;
                pw.println("      " + cmpt);
            }
            }

            pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
            for (ManagedServiceInfo info : mServices) {
@@ -472,25 +442,12 @@ abstract public class ManagedServices {
            }
        }


        synchronized (mMutex) {
            if (managedServicesConcurrentMultiuser()) {
                for (int i = 0; i < mEnabledServicesByUser.size(); i++) {
                    final int userId = mEnabledServicesByUser.keyAt(i);
                    final ArraySet<ComponentName> componentNames =
                            mEnabledServicesByUser.get(userId);
                    for (ComponentName cmpt : componentNames) {
                        if (filter != null && !filter.matches(cmpt)) continue;
                        cmpt.dumpDebug(proto, ManagedServicesProto.ENABLED);
                    }
                }
            } else {
                final ArraySet<ComponentName> enabledServicesForCurrentProfiles =
                        mEnabledServicesByUser.get(UserHandle.USER_CURRENT);
                for (ComponentName cmpt : enabledServicesForCurrentProfiles) {
            for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
                if (filter != null && !filter.matches(cmpt)) continue;
                cmpt.dumpDebug(proto, ManagedServicesProto.ENABLED);
            }
            }
            for (ManagedServiceInfo info : mServices) {
                if (filter != null && !filter.matches(info.component)) continue;
                info.dumpDebug(proto, ManagedServicesProto.LIVE_SERVICES, this);
@@ -884,31 +841,9 @@ abstract public class ManagedServices {
        }
    }

    /** convenience method for looking in mEnabledServicesPackageNamesByUser
     * for UserHandle.USER_CURRENT.
     * This is a legacy API. When FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER becomes
     * trunk stable,  this API should be deprecated.  Additionally, when this method
     * is deprecated, the unit tests written using this method should also be revised.
     *
     * @param pkg target package name
     * @return boolean value that indicates whether it is enabled for the current profiles
     */
    protected boolean isComponentEnabledForPackage(String pkg) {
        return isComponentEnabledForPackage(pkg, UserHandle.USER_CURRENT);
    }

    /** convenience method for looking in mEnabledServicesPackageNamesByUser
     *
     * @param pkg target package name
     * @param userId the id of the target user
     * @return boolean value that indicates whether it is enabled for the target user
     */
    @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
    protected boolean isComponentEnabledForPackage(String pkg, int userId) {
        synchronized (mMutex) {
            ArraySet<String> enabledServicesPackageNames =
                    mEnabledServicesPackageNamesByUser.get(resolveUserId(userId));
            return enabledServicesPackageNames != null && enabledServicesPackageNames.contains(pkg);
            return mEnabledServicesPackageNames.contains(pkg);
        }
    }

@@ -1081,14 +1016,9 @@ abstract public class ManagedServices {
    public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) {
        if (DEBUG) {
            synchronized (mMutex) {
                int resolvedUserId = (managedServicesConcurrentMultiuser()
                        && (uidList != null && uidList.length > 0))
                        ? resolveUserId(UserHandle.getUserId(uidList[0]))
                        : UserHandle.USER_CURRENT;
                Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
                        + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
                        + " mEnabledServicesPackageNames="
                        + mEnabledServicesPackageNamesByUser.get(resolvedUserId));
                        + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
            }
        }

@@ -1104,18 +1034,11 @@ abstract public class ManagedServices {
                }
            }
            for (String pkgName : pkgList) {
                if (!managedServicesConcurrentMultiuser()) {
                if (isComponentEnabledForPackage(pkgName)) {
                    anyServicesInvolved = true;
                }
                }
                if (uidList != null && uidList.length > 0) {
                    for (int uid : uidList) {
                        if (managedServicesConcurrentMultiuser()) {
                            if (isComponentEnabledForPackage(pkgName, UserHandle.getUserId(uid))) {
                                anyServicesInvolved = true;
                            }
                        }
                        if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
                            anyServicesInvolved = true;
                            trimApprovedListsForInvalidServices(pkgName, UserHandle.getUserId(uid));
@@ -1142,36 +1065,6 @@ abstract public class ManagedServices {
        unbindUserServices(user);
    }

    /**
     * Call this method when a user is stopped
     *
     * @param user the id of the stopped user
     */
    public void onUserStopped(int user) {
        if (!managedServicesConcurrentMultiuser()) {
            return;
        }
        boolean hasAny = false;
        synchronized (mMutex) {
            if (mEnabledServicesByUser.contains(user)
                    && mEnabledServicesPackageNamesByUser.contains(user)) {
                // Through the ManagedServices.resolveUserId,
                // we resolve UserHandle.USER_CURRENT as the key for users
                // other than the visible background user.
                // Therefore, the user IDs that exist as keys for each member variable
                // correspond to the visible background user.
                // We need to unbind services of the stopped visible background user.
                mEnabledServicesByUser.remove(user);
                mEnabledServicesPackageNamesByUser.remove(user);
                hasAny = true;
            }
        }
        if (hasAny) {
            Slog.i(TAG, "Removing approved services for stopped user " + user);
            unbindUserServices(user);
        }
    }

    public void onUserSwitched(int user) {
        if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
        unbindOtherUserServices(user);
@@ -1493,42 +1386,19 @@ abstract public class ManagedServices {
    protected void populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind,
            final IntArray activeUsers,
            SparseArray<ArraySet<ComponentName>> approvedComponentsByUser) {
        mEnabledServicesForCurrentProfiles.clear();
        mEnabledServicesPackageNames.clear();
        final int nUserIds = activeUsers.size();
        if (managedServicesConcurrentMultiuser()) {
            for (int i = 0; i < nUserIds; ++i) {
                final int resolvedUserId = resolveUserId(activeUsers.get(i));
                if (mEnabledServicesByUser.get(resolvedUserId) != null) {
                    mEnabledServicesByUser.get(resolvedUserId).clear();
                }
                if (mEnabledServicesPackageNamesByUser.get(resolvedUserId) != null) {
                    mEnabledServicesPackageNamesByUser.get(resolvedUserId).clear();
                }
            }
        } else {
            mEnabledServicesByUser.clear();
            mEnabledServicesPackageNamesByUser.clear();
        }

        for (int i = 0; i < nUserIds; ++i) {
            final int userId = activeUsers.get(i);
            // decode the list of components
            final int userId = activeUsers.get(i);
            final ArraySet<ComponentName> userComponents = approvedComponentsByUser.get(userId);
            if (null == userComponents) {
                componentsToBind.put(userId, new ArraySet<>());
                continue;
            }

            final int resolvedUserId = managedServicesConcurrentMultiuser()
                    ? resolveUserId(userId)
                    : UserHandle.USER_CURRENT;
            ArraySet<ComponentName> enabledServices =
                    mEnabledServicesByUser.contains(resolvedUserId)
                    ? mEnabledServicesByUser.get(resolvedUserId)
                    : new ArraySet<>();
            ArraySet<String> enabledServicesPackageName =
                    mEnabledServicesPackageNamesByUser.contains(resolvedUserId)
                    ? mEnabledServicesPackageNamesByUser.get(resolvedUserId)
                    : new ArraySet<>();

            final Set<ComponentName> add = new HashSet<>(userComponents);
            synchronized (mSnoozing) {
                ArraySet<ComponentName> snoozed = mSnoozing.get(userId);
@@ -1539,12 +1409,12 @@ abstract public class ManagedServices {

            componentsToBind.put(userId, add);

            enabledServices.addAll(userComponents);
            mEnabledServicesForCurrentProfiles.addAll(userComponents);

            for (int j = 0; j < userComponents.size(); j++) {
                enabledServicesPackageName.add(userComponents.valueAt(j).getPackageName());
                final ComponentName component = userComponents.valueAt(j);
                mEnabledServicesPackageNames.add(component.getPackageName());
            }
            mEnabledServicesByUser.put(resolvedUserId, enabledServices);
            mEnabledServicesPackageNamesByUser.put(resolvedUserId, enabledServicesPackageName);
        }
    }

@@ -1583,9 +1453,13 @@ abstract public class ManagedServices {
     */
    protected void rebindServices(boolean forceRebind, int userToRebind) {
        if (DEBUG) Slog.d(TAG, "rebindServices " + forceRebind + " " + userToRebind);
        IntArray userIds = mUserProfiles.getCurrentProfileIds();
        boolean rebindAllCurrentUsers = mUserProfiles.isProfileUser(userToRebind, mContext)
                && allowRebindForParentUser();
        IntArray userIds = getUserIdsForRebindServices(userToRebind, rebindAllCurrentUsers);
        if (userToRebind != USER_ALL && !rebindAllCurrentUsers) {
            userIds = new IntArray(1);
            userIds.add(userToRebind);
        }

        final SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();
        final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();
@@ -1609,23 +1483,6 @@ abstract public class ManagedServices {
        bindToServices(componentsToBind);
    }

    private IntArray getUserIdsForRebindServices(int userToRebind, boolean rebindAllCurrentUsers) {
        IntArray userIds = mUserProfiles.getCurrentProfileIds();
        if (userToRebind != USER_ALL && !rebindAllCurrentUsers) {
            userIds = new IntArray(1);
            userIds.add(userToRebind);
        } else if (managedServicesConcurrentMultiuser()
                && userToRebind == USER_ALL) {
            for (UserInfo user : mUm.getUsers()) {
                if (mUmInternal.isVisibleBackgroundFullUser(user.id)
                        && !userIds.contains(user.id)) {
                    userIds.add(user.id);
                }
            }
        }
        return userIds;
    }

    /**
     * Called when user switched to unbind all services from other users.
     */
@@ -1649,11 +1506,7 @@ abstract public class ManagedServices {
        synchronized (mMutex) {
            final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices();
            for (ManagedServiceInfo info : removableBoundServices) {
                // User switching is the event for the forground user.
                // It should not affect the service of the visible background user.
                if ((allExceptUser && (info.userid != user)
                        && !(managedServicesConcurrentMultiuser()
                            && info.isVisibleBackgroundUserService))
                if ((allExceptUser && (info.userid != user))
                        || (!allExceptUser && (info.userid == user))) {
                    Set<ComponentName> toUnbind =
                            componentsToUnbind.get(info.userid, new ArraySet<>());
@@ -2007,29 +1860,6 @@ abstract public class ManagedServices {
        return true;
    }

    /**
     * This method returns the mapped id for the incoming user id
     * If the incoming id was not the id of the visible background user, it returns USER_CURRENT.
     * In the other cases, it returns the same value as the input.
     *
     * @param userId the id of the user
     * @return the user id if it is a visible background user, otherwise
     * {@link UserHandle#USER_CURRENT}
     */
    @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
    @VisibleForTesting
    public int resolveUserId(int userId) {
        if (managedServicesConcurrentMultiuser()) {
            if (mUmInternal.isVisibleBackgroundFullUser(userId)) {
                // The dataset of the visible background user should be managed independently.
                return userId;
            }
        }
        // The data of current user and its profile users need to  be managed
        // in a dataset as before.
        return UserHandle.USER_CURRENT;
    }

    /**
     * Returns true if services in the parent user should be rebound
     *  when rebindServices is called with a profile userId.
@@ -2048,8 +1878,6 @@ abstract public class ManagedServices {
        public int targetSdkVersion;
        public Pair<ComponentName, Integer> mKey;
        public int uid;
        @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
        public boolean isVisibleBackgroundUserService;

        public ManagedServiceInfo(IInterface service, ComponentName component,
                int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion,
@@ -2061,10 +1889,6 @@ abstract public class ManagedServices {
            this.connection = connection;
            this.targetSdkVersion = targetSdkVersion;
            this.uid = uid;
            if (managedServicesConcurrentMultiuser()) {
                this.isVisibleBackgroundUserService = LocalServices
                        .getService(UserManagerInternal.class).isVisibleBackgroundFullUser(userid);
            }
            mKey = Pair.create(component, userid);
        }

@@ -2113,28 +1937,19 @@ abstract public class ManagedServices {
        }

        public boolean isSameUser(int userId) {
            if (!isEnabledForUser()) {
            if (!isEnabledForCurrentProfiles()) {
                return false;
            }
            return userId == USER_ALL || userId == this.userid;
        }

        public boolean enabledAndUserMatches(int nid) {
            if (!isEnabledForUser()) {
            if (!isEnabledForCurrentProfiles()) {
                return false;
            }
            if (this.userid == USER_ALL) return true;
            if (this.isSystem) return true;
            if (nid == USER_ALL || nid == this.userid) return true;
            if (managedServicesConcurrentMultiuser()
                    && mUmInternal.getProfileParentId(nid)
                        != mUmInternal.getProfileParentId(this.userid)) {
                // If the profile parent IDs do not match each other,
                // it is determined that the users do not match.
                // This situation may occur when comparing the current user's ID
                // with the visible background user's ID.
                return false;
            }
            return supportsProfiles()
                    && mUserProfiles.isCurrentProfile(nid)
                    && isPermittedForProfile(nid);
@@ -2154,21 +1969,12 @@ abstract public class ManagedServices {
            removeServiceImpl(this.service, this.userid);
        }

        /**
         * convenience method for looking in mEnabledServicesByUser.
         * If FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER is disabled, this manages the data using
         * only UserHandle.USER_CURRENT as the key, in order to behave the same as the legacy logic.
        */
        public boolean isEnabledForUser() {
        /** convenience method for looking in mEnabledServicesForCurrentProfiles */
        public boolean isEnabledForCurrentProfiles() {
            if (this.isSystem) return true;
            if (this.connection == null) return false;
            synchronized (mMutex) {
                int resolvedUserId = managedServicesConcurrentMultiuser()
                        ? resolveUserId(this.userid)
                        : UserHandle.USER_CURRENT;
                ArraySet<ComponentName> enabledServices =
                        mEnabledServicesByUser.get(resolvedUserId);
                return enabledServices != null && enabledServices.contains(this.component);
                return mEnabledServicesForCurrentProfiles.contains(this.component);
            }
        }

@@ -2211,30 +2017,10 @@ abstract public class ManagedServices {
        }
    }

    /** convenience method for looking in mEnabledServicesByUser for UserHandle.USER_CURRENT.
     * This is a legacy API. When FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER becomes
     * trunk stable,  this API should be deprecated.  Additionally, when this method
     * is deprecated, the unit tests written using this method should also be revised.
     *
     * @param component target component name
     * @return boolean value that indicates whether it is enabled for the current profiles
     */
    /** convenience method for looking in mEnabledServicesForCurrentProfiles */
    public boolean isComponentEnabledForCurrentProfiles(ComponentName component) {
        return isComponentEnabledForUser(component, UserHandle.USER_CURRENT);
    }

    /** convenience method for looking in mEnabledServicesForUser
     *
     * @param component target component name
     * @param userId the id of the target user
     * @return boolean value that indicates whether it is enabled for the target user
    */
    @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
    public boolean isComponentEnabledForUser(ComponentName component, int userId) {
        synchronized (mMutex) {
            ArraySet<ComponentName> enabledServicesForUser =
                    mEnabledServicesByUser.get(resolveUserId(userId));
            return enabledServicesForUser != null && enabledServicesForUser.contains(component);
            return mEnabledServicesForCurrentProfiles.contains(component);
        }
    }

+16 −30

File changed.

Preview size limit exceeded, changes collapsed.

+0 −7
Original line number Diff line number Diff line
@@ -210,10 +210,3 @@ flag {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "managed_services_concurrent_multiuser"
  namespace: "systemui"
  description: "Enables ManagedServices to support Concurrent multi user environment"
  bug: "380297485"
}
+0 −1
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ android_test {
        "androidx.test.rules",
        "hamcrest-library",
        "mockito-target-inline-minus-junit4",
        "mockito-target-extended",
        "platform-compat-test-rules",
        "platform-test-annotations",
        "platformprotosnano",
+0 −4
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.testing.TestableContext;

import androidx.test.InstrumentationRegistry;

import com.android.server.pm.UserManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;

import org.junit.After;
@@ -42,7 +41,6 @@ import org.mockito.MockitoAnnotations;

public class UiServiceTestCase {
    @Mock protected PackageManagerInternal mPmi;
    @Mock protected UserManagerInternal mUmi;
    @Mock protected UriGrantsManagerInternal mUgmInternal;

    protected static final String PKG_N_MR1 = "com.example.n_mr1";
@@ -94,8 +92,6 @@ public class UiServiceTestCase {
                    }
                });

        LocalServices.removeServiceForTest(UserManagerInternal.class);
        LocalServices.addService(UserManagerInternal.class, mUmi);
        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
        LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
        when(mUgmInternal.checkGrantUriPermission(
Loading