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

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

Merge "Check for NLS bind permission when rebinding services" into tm-dev

parents 9edafbe9 f126be35
Loading
Loading
Loading
Loading
+82 −24
Original line number Original line Diff line number Diff line
@@ -901,6 +901,23 @@ abstract public class ManagedServices {
        return false;
        return false;
    }
    }


    protected boolean isPackageOrComponentAllowedWithPermission(ComponentName component,
            int userId) {
        if (!(isPackageOrComponentAllowed(component.flattenToString(), userId)
                || isPackageOrComponentAllowed(component.getPackageName(), userId))) {
            return false;
        }
        return componentHasBindPermission(component, userId);
    }

    private boolean componentHasBindPermission(ComponentName component, int userId) {
        ServiceInfo info = getServiceInfo(component, userId);
        if (info == null) {
            return false;
        }
        return mConfig.bindPermission.equals(info.permission);
    }

    boolean isPackageOrComponentUserSet(String pkgOrComponent, int userId) {
    boolean isPackageOrComponentUserSet(String pkgOrComponent, int userId) {
        synchronized (mApproved) {
        synchronized (mApproved) {
            ArraySet<String> services = mUserSetServices.get(userId);
            ArraySet<String> services = mUserSetServices.get(userId);
@@ -958,6 +975,7 @@ abstract public class ManagedServices {
                    for (int uid : uidList) {
                    for (int uid : uidList) {
                        if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
                        if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
                            anyServicesInvolved = true;
                            anyServicesInvolved = true;
                            trimApprovedListsForInvalidServices(pkgName, UserHandle.getUserId(uid));
                        }
                        }
                    }
                    }
                }
                }
@@ -1083,8 +1101,7 @@ abstract public class ManagedServices {


        synchronized (mMutex) {
        synchronized (mMutex) {
            if (enabled) {
            if (enabled) {
                if (isPackageOrComponentAllowed(component.flattenToString(), userId)
                if (isPackageOrComponentAllowedWithPermission(component, userId)) {
                        || isPackageOrComponentAllowed(component.getPackageName(), userId)) {
                    registerServiceLocked(component, userId);
                    registerServiceLocked(component, userId);
                } else {
                } else {
                    Slog.d(TAG, component + " no longer has permission to be bound");
                    Slog.d(TAG, component + " no longer has permission to be bound");
@@ -1222,6 +1239,33 @@ abstract public class ManagedServices {
        return removed;
        return removed;
    }
    }


    private void trimApprovedListsForInvalidServices(String packageName, int userId) {
        synchronized (mApproved) {
            final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
            if (approvedByType == null) {
                return;
            }
            for (int i = 0; i < approvedByType.size(); i++) {
                final ArraySet<String> approved = approvedByType.valueAt(i);
                for (int j = approved.size() - 1; j >= 0; j--) {
                    final String approvedPackageOrComponent = approved.valueAt(j);
                    if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) {
                        final ComponentName component = ComponentName.unflattenFromString(
                                approvedPackageOrComponent);
                        if (component != null && !componentHasBindPermission(component, userId)) {
                            approved.removeAt(j);
                            if (DEBUG) {
                                Slog.v(TAG, "Removing " + approvedPackageOrComponent
                                        + " from approved list; no bind permission found "
                                        + mConfig.bindPermission);
                            }
                        }
                    }
                }
            }
        }
    }

    protected String getPackageName(String packageOrComponent) {
    protected String getPackageName(String packageOrComponent) {
        final ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
        final ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
        if (component != null) {
        if (component != null) {
@@ -1405,12 +1449,7 @@ abstract public class ManagedServices {
            final int userId = componentsToBind.keyAt(i);
            final int userId = componentsToBind.keyAt(i);
            final Set<ComponentName> add = componentsToBind.get(userId);
            final Set<ComponentName> add = componentsToBind.get(userId);
            for (ComponentName component : add) {
            for (ComponentName component : add) {
                try {
                ServiceInfo info = getServiceInfo(component, userId);
                    ServiceInfo info = mPm.getServiceInfo(component,
                            PackageManager.GET_META_DATA
                                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                            userId);
                if (info == null) {
                if (info == null) {
                    Slog.w(TAG, "Not binding " + getCaption() + " service " + component
                    Slog.w(TAG, "Not binding " + getCaption() + " service " + component
                            + ": service not found");
                            + ": service not found");
@@ -1424,9 +1463,6 @@ abstract public class ManagedServices {
                Slog.v(TAG,
                Slog.v(TAG,
                        "enabling " + getCaption() + " for " + userId + ": " + component);
                        "enabling " + getCaption() + " for " + userId + ": " + component);
                registerService(info, userId);
                registerService(info, userId);
                } catch (RemoteException e) {
                    e.rethrowFromSystemServer();
                }
            }
            }
        }
        }
    }
    }
@@ -1447,6 +1483,15 @@ abstract public class ManagedServices {
        }
        }
    }
    }


    @VisibleForTesting
    void reregisterService(final ComponentName cn, final int userId) {
        // If rebinding a package that died, ensure it still has permission
        // after the rebind delay
        if (isPackageOrComponentAllowedWithPermission(cn, userId)) {
            registerService(cn, userId);
        }
    }

    /**
    /**
     * Inject a system service into the management list.
     * Inject a system service into the management list.
     */
     */
@@ -1548,7 +1593,7 @@ abstract public class ManagedServices {
                            mHandler.postDelayed(new Runnable() {
                            mHandler.postDelayed(new Runnable() {
                                    @Override
                                    @Override
                                    public void run() {
                                    public void run() {
                                        registerService(name, userid);
                                        reregisterService(name, userid);
                                    }
                                    }
                               }, ON_BINDING_DIED_REBIND_DELAY_MS);
                               }, ON_BINDING_DIED_REBIND_DELAY_MS);
                        } else {
                        } else {
@@ -1680,6 +1725,19 @@ abstract public class ManagedServices {
        }
        }
    }
    }


    private ServiceInfo getServiceInfo(ComponentName component, int userId) {
        try {
            return mPm.getServiceInfo(component,
                    PackageManager.GET_META_DATA
                            | PackageManager.MATCH_DIRECT_BOOT_AWARE
                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                    userId);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        return null;
    }

    public class ManagedServiceInfo implements IBinder.DeathRecipient {
    public class ManagedServiceInfo implements IBinder.DeathRecipient {
        public IInterface service;
        public IInterface service;
        public ComponentName component;
        public ComponentName component;
+54 −0
Original line number Original line Diff line number Diff line
@@ -28,8 +28,10 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;
@@ -958,6 +960,58 @@ public class ManagedServicesTest extends UiServiceTestCase {
        }
        }
    }
    }


    @Test
    public void testUpgradeAppNoPermissionNoRebind() throws Exception {
        Context context = spy(getContext());
        doReturn(true).when(context).bindServiceAsUser(any(), any(), anyInt(), any());

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles,
                mIpm,
                APPROVAL_BY_COMPONENT);

        List<String> packages = new ArrayList<>();
        packages.add("package");
        addExpectedServices(service, packages, 0);

        final ComponentName unapprovedComponent = ComponentName.unflattenFromString("package/C1");
        final ComponentName approvedComponent = ComponentName.unflattenFromString("package/C2");

        // Both components are approved initially
        mExpectedPrimaryComponentNames.clear();
        mExpectedPrimaryPackages.clear();
        mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
        mExpectedSecondaryComponentNames.clear();
        mExpectedSecondaryPackages.clear();

        loadXml(service);

        //Component package/C1 loses bind permission
        when(mIpm.getServiceInfo(any(), anyLong(), anyInt())).thenAnswer(
                (Answer<ServiceInfo>) invocation -> {
                    ComponentName invocationCn = invocation.getArgument(0);
                    if (invocationCn != null) {
                        ServiceInfo serviceInfo = new ServiceInfo();
                        serviceInfo.packageName = invocationCn.getPackageName();
                        serviceInfo.name = invocationCn.getClassName();
                        if (invocationCn.equals(unapprovedComponent)) {
                            serviceInfo.permission = "none";
                        } else {
                            serviceInfo.permission = service.getConfig().bindPermission;
                        }
                        serviceInfo.metaData = null;
                        return serviceInfo;
                    }
                    return null;
                }
        );

        // Trigger package update
        service.onPackagesChanged(false, new String[]{"package"}, new int[]{0});

        assertFalse(service.isComponentEnabledForCurrentProfiles(unapprovedComponent));
        assertTrue(service.isComponentEnabledForCurrentProfiles(approvedComponent));
    }

    @Test
    @Test
    public void testSetPackageOrComponentEnabled() throws Exception {
    public void testSetPackageOrComponentEnabled() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {