diff options
| author | 2019-01-13 09:53:12 -0800 | |
|---|---|---|
| committer | 2019-01-13 11:07:26 -0800 | |
| commit | 5e5c41e549a7c4c770ed62afe927b0a36a626ef8 (patch) | |
| tree | 8460a86b8791650a70b502515afe9c32389de9de | |
| parent | 485251a185dfd70e145f2f2f4bca9fef15d31c3c (diff) | |
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
| -rw-r--r-- | core/java/android/permission/PermissionControllerManager.java | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java index e21a6608bee0..d7332ae92fb5 100644 --- a/core/java/android/permission/PermissionControllerManager.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -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,17 +147,27 @@ 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) { - Intent intent = new Intent(SERVICE_INTERFACE); - intent.setPackage(context.getPackageManager().getPermissionControllerPackageName()); - ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0); + synchronized (sLock) { + if (sRemoteService == null) { + Intent intent = new Intent(SERVICE_INTERFACE); + intent.setPackage(context.getPackageManager().getPermissionControllerPackageName()); + ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0); + + sRemoteService = new RemoteService(context.getApplicationContext(), + serviceInfo.getComponentInfo().getComponentName()); + } + } mContext = context; - mRemoteService = new RemoteService(context, - serviceInfo.getComponentInfo().getComponentName()); } /** @@ -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)); } /** |