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

Commit 5e5c41e5 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Have app global connection as to other managers

Regular ...Manager-s connect to the system server hence there is no
problem establishing a permanent connection via
ServiceManager.getServiceOrThrow.

(1)
PermissionControllerManager connects to an app, hence the binding has to
be dynamic. This is done my using the local RemoteService class.

(2)
...Manager-s are per context. Hence when the context goes away all
service connection started for this service are supposed to also be
cleaned up. There is no callback when the context goes away.

(1) and (2) lead to RemoteService connection to still be bound while the
context goes away which causes a service connection leak.

This change emulates the behavior of regular managers by creating a
permanent RemoteService tied to the application context. Of course
interanlly RemoteService itself binds and unbinds dynamically. Still,
now the RemoteService is not bound to a context that goes away and no
connection is leaked.

Test: atest CtsAppSecurityHostTestCases:android.appsecurity.cts.PermissionsHostTest
      (this test failed before as settings was crashing due to leaked
      remote service connections)
Change-Id: I5b8a4c62070fcce6e390897d046c4b28998e3952
parent 485251a1
Loading
Loading
Loading
Loading
+30 −13
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
import com.android.internal.infra.AbstractRemoteService;
import com.android.internal.util.Preconditions;
@@ -68,6 +69,12 @@ import java.util.concurrent.Executor;
public final class PermissionControllerManager {
    private static final String TAG = PermissionControllerManager.class.getSimpleName();

    private static final Object sLock = new Object();

    /** App global remote service used by all {@link PermissionControllerManager managers} */
    @GuardedBy("sLock")
    private static RemoteService sRemoteService;

    /**
     * The key for retrieving the result from the returned bundle.
     *
@@ -140,18 +147,28 @@ public final class PermissionControllerManager {
    }

    private final @NonNull Context mContext;
    private final RemoteService mRemoteService;

    /** @hide */
    /**
     * Create a new {@link PermissionControllerManager}.
     *
     * @param context to create the manager for
     *
     * @hide
     */
    public PermissionControllerManager(@NonNull Context context) {
        synchronized (sLock) {
            if (sRemoteService == null) {
                Intent intent = new Intent(SERVICE_INTERFACE);
                intent.setPackage(context.getPackageManager().getPermissionControllerPackageName());
                ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0);

        mContext = context;
        mRemoteService = new RemoteService(context,
                sRemoteService = new RemoteService(context.getApplicationContext(),
                        serviceInfo.getComponentInfo().getComponentName());
            }
        }

        mContext = context;
    }

    /**
     * Revoke a set of runtime permissions for various apps.
@@ -182,7 +199,7 @@ public final class PermissionControllerManager {
                    + " required");
        }

        mRemoteService.scheduleRequest(new PendingRevokeRuntimePermissionRequest(mRemoteService,
        sRemoteService.scheduleRequest(new PendingRevokeRuntimePermissionRequest(sRemoteService,
                request, doDryRun, reason, mContext.getPackageName(), executor, callback));
    }

@@ -201,8 +218,8 @@ public final class PermissionControllerManager {
        checkNotNull(packageName);
        checkNotNull(callback);

        mRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(mRemoteService,
                packageName, callback, handler == null ? mRemoteService.getHandler() : handler));
        sRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(sRemoteService,
                packageName, callback, handler == null ? sRemoteService.getHandler() : handler));
    }

    /**
@@ -219,7 +236,7 @@ public final class PermissionControllerManager {
        checkNotNull(packageName);
        checkNotNull(permissionName);

        mRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
        sRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
                permissionName));
    }

@@ -241,9 +258,9 @@ public final class PermissionControllerManager {
        checkCollectionElementsNotNull(permissionNames, "permissionNames");
        checkNotNull(callback);

        mRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(mRemoteService,
        sRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(sRemoteService,
                permissionNames, countOnlyGranted, countSystem, callback,
                handler == null ? mRemoteService.getHandler() : handler));
                handler == null ? sRemoteService.getHandler() : handler));
    }

    /**