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

Commit 5051dd69 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Check that an app still has access while rebinding

In case the permission state changed during the rebind delay

Fixes: 210987139
Test: ManagedServicesTest
Change-Id: Id435fe32e778588b22e3fc12c0f5d16a6562cb4f
parent 1097ed3c
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -1447,6 +1447,16 @@ 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 (isPackageOrComponentAllowed(cn.getPackageName(), userId)
                || isPackageOrComponentAllowed(cn.flattenToString(), userId)) {
            registerService(cn, userId);
        }
    }

    /**
     * Inject a system service into the management list.
     */
@@ -1545,12 +1555,9 @@ abstract public class ManagedServices {
                        unbindService(this, name, userid);
                        if (!mServicesRebinding.contains(servicesBindingTag)) {
                            mServicesRebinding.add(servicesBindingTag);
                            mHandler.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        registerService(name, userid);
                                    }
                               }, ON_BINDING_DIED_REBIND_DELAY_MS);
                            mHandler.postDelayed(() ->
                                    reregisterService(name, userid),
                                    ON_BINDING_DIED_REBIND_DELAY_MS);
                        } else {
                            Slog.v(TAG, getCaption() + " not rebinding in user " + userid
                                    + " as a previous rebind attempt was made: " + name);
+150 −0
Original line number Diff line number Diff line
@@ -839,6 +839,156 @@ public class ManagedServicesTest extends UiServiceTestCase {
        verifyExpectedBoundEntries(service, false);
    }

    @Test
    public void reregisterService_checksAppIsApproved_pkg() throws Exception {
        Context context = mock(Context.class);
        PackageManager pm = mock(PackageManager.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;

        when(context.getPackageName()).thenReturn(mContext.getPackageName());
        when(context.getUserId()).thenReturn(mContext.getUserId());
        when(context.getPackageManager()).thenReturn(pm);
        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
                APPROVAL_BY_PACKAGE);
        ComponentName cn = ComponentName.unflattenFromString("a/a");

        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            ServiceConnection sc = (ServiceConnection) args[1];
            sc.onServiceConnected(cn, mock(IBinder.class));
            return true;
        });

        service.addApprovedList("a", 0, true);

        service.reregisterService(cn, 0);

        assertTrue(service.isBound(cn, 0));
    }

    @Test
    public void reregisterService_checksAppIsApproved_pkg_secondary() throws Exception {
        Context context = mock(Context.class);
        PackageManager pm = mock(PackageManager.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;

        when(context.getPackageName()).thenReturn(mContext.getPackageName());
        when(context.getUserId()).thenReturn(mContext.getUserId());
        when(context.getPackageManager()).thenReturn(pm);
        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
                APPROVAL_BY_PACKAGE);
        ComponentName cn = ComponentName.unflattenFromString("a/a");

        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            ServiceConnection sc = (ServiceConnection) args[1];
            sc.onServiceConnected(cn, mock(IBinder.class));
            return true;
        });

        service.addApprovedList("a", 0, false);

        service.reregisterService(cn, 0);

        assertTrue(service.isBound(cn, 0));
    }

    @Test
    public void reregisterService_checksAppIsApproved_cn() throws Exception {
        Context context = mock(Context.class);
        PackageManager pm = mock(PackageManager.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;

        when(context.getPackageName()).thenReturn(mContext.getPackageName());
        when(context.getUserId()).thenReturn(mContext.getUserId());
        when(context.getPackageManager()).thenReturn(pm);
        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);
        ComponentName cn = ComponentName.unflattenFromString("a/a");

        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            ServiceConnection sc = (ServiceConnection) args[1];
            sc.onServiceConnected(cn, mock(IBinder.class));
            return true;
        });

        service.addApprovedList("a/a", 0, true);

        service.reregisterService(cn, 0);

        assertTrue(service.isBound(cn, 0));
    }

    @Test
    public void reregisterService_checksAppIsApproved_cn_secondary() throws Exception {
        Context context = mock(Context.class);
        PackageManager pm = mock(PackageManager.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;

        when(context.getPackageName()).thenReturn(mContext.getPackageName());
        when(context.getUserId()).thenReturn(mContext.getUserId());
        when(context.getPackageManager()).thenReturn(pm);
        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);
        ComponentName cn = ComponentName.unflattenFromString("a/a");

        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            ServiceConnection sc = (ServiceConnection) args[1];
            sc.onServiceConnected(cn, mock(IBinder.class));
            return true;
        });

        service.addApprovedList("a/a", 0, false);

        service.reregisterService(cn, 0);

        assertTrue(service.isBound(cn, 0));
    }

    @Test
    public void reregisterService_checksAppIsNotApproved_cn_secondary() throws Exception {
        Context context = mock(Context.class);
        PackageManager pm = mock(PackageManager.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;

        when(context.getPackageName()).thenReturn(mContext.getPackageName());
        when(context.getUserId()).thenReturn(mContext.getUserId());
        when(context.getPackageManager()).thenReturn(pm);
        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);
        ComponentName cn = ComponentName.unflattenFromString("a/a");

        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            ServiceConnection sc = (ServiceConnection) args[1];
            sc.onServiceConnected(cn, mock(IBinder.class));
            return true;
        });

        service.addApprovedList("b/b", 0, false);

        service.reregisterService(cn, 0);

        assertFalse(service.isBound(cn, 0));
    }

    @Test
    public void unbindOtherUserServices() throws PackageManager.NameNotFoundException {
        Context context = mock(Context.class);