summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Philip P. Moltmann <moltmann@google.com> 2019-01-13 09:53:12 -0800
committer Philip P. Moltmann <moltmann@google.com> 2019-01-13 11:07:26 -0800
commit5e5c41e549a7c4c770ed62afe927b0a36a626ef8 (patch)
tree8460a86b8791650a70b502515afe9c32389de9de
parent485251a185dfd70e145f2f2f4bca9fef15d31c3c (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.java43
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));
}
/**