summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ryan Mitchell <rtmitchell@google.com> 2019-07-19 14:24:52 -0700
committer android-build-merger <android-build-merger@google.com> 2019-07-19 14:24:52 -0700
commite5786b7ab8991d559ca2dab758e0e8a7be2f84e0 (patch)
treec1ba5f34e36daa3b89c107940a8c2c3f2c2f2027
parenta50e7bb20dc75c865ea0b535a34090700b9db318 (diff)
parent4b09d08c6c26bff1406b5785dd9942c764ffce49 (diff)
Merge "Revert "Stop idmap2d after several seconds pass"" into qt-r1-dev
am: 4b09d08c6c Change-Id: I7e6d5d4f5245319fc3fcbfe27c16f11ad80eb9c2
-rw-r--r--services/core/java/com/android/server/om/IdmapDaemon.java193
-rw-r--r--services/core/java/com/android/server/om/IdmapManager.java59
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java1
3 files changed, 49 insertions, 204 deletions
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
deleted file mode 100644
index 55fbcb4344cf..000000000000
--- a/services/core/java/com/android/server/om/IdmapDaemon.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.om;
-
-import static android.content.Context.IDMAP_SERVICE;
-
-import static com.android.server.om.OverlayManagerService.DEBUG;
-import static com.android.server.om.OverlayManagerService.TAG;
-
-import android.os.IBinder;
-import android.os.IIdmap2;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.util.Slog;
-
-import com.android.server.IoThread;
-
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * To prevent idmap2d from continuously running, the idmap daemon will terminate after 10
- * seconds without a transaction.
- **/
-class IdmapDaemon {
- // The amount of time in milliseconds to wait after a transaction to the idmap service is made
- // before stopping the service.
- private static final int SERVICE_TIMEOUT_MS = 10000;
-
- // The amount of time in milliseconds to wait when attempting to connect to idmap service.
- private static final int SERVICE_CONNECT_TIMEOUT_MS = 5000;
-
- private static final Object IDMAP_TOKEN = new Object();
- private static final String IDMAP_DAEMON = "idmap2d";
-
- private static IdmapDaemon sInstance;
- private volatile IIdmap2 mService;
- private final AtomicInteger mOpenedCount = new AtomicInteger();
-
- /**
- * An {@link AutoCloseable} connection to the idmap service. When the connection is closed or
- * finalized, the idmap service will be stopped after a period of time unless another connection
- * to the service is open.
- **/
- private class Connection implements AutoCloseable {
- private boolean mOpened = true;
-
- private Connection() {
- synchronized (IDMAP_TOKEN) {
- mOpenedCount.incrementAndGet();
- }
- }
-
- @Override
- public void close() {
- synchronized (IDMAP_TOKEN) {
- if (!mOpened) {
- return;
- }
-
- mOpened = false;
- if (mOpenedCount.decrementAndGet() != 0) {
- // Only post the callback to stop the service if the service does not have an
- // open connection.
- return;
- }
-
- IoThread.getHandler().postDelayed(() -> {
- synchronized (IDMAP_TOKEN) {
- // Only stop the service if the service does not have an open connection.
- if (mService == null || mOpenedCount.get() != 0) {
- return;
- }
-
- stopIdmapService();
- mService = null;
- }
- }, IDMAP_TOKEN, SERVICE_TIMEOUT_MS);
- }
- }
- }
-
- static IdmapDaemon getInstance() {
- if (sInstance == null) {
- sInstance = new IdmapDaemon();
- }
- return sInstance;
- }
-
- String createIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
- int userId) throws Exception {
- try (Connection connection = connect()) {
- return mService.createIdmap(targetPath, overlayPath, policies, enforce, userId);
- }
- }
-
- boolean removeIdmap(String overlayPath, int userId) throws Exception {
- try (Connection connection = connect()) {
- return mService.removeIdmap(overlayPath, userId);
- }
- }
-
- boolean verifyIdmap(String overlayPath, int policies, boolean enforce, int userId)
- throws Exception {
- try (Connection connection = connect()) {
- return mService.verifyIdmap(overlayPath, policies, enforce, userId);
- }
- }
-
- String getIdmapPath(String overlayPath, int userId) throws Exception {
- try (Connection connection = connect()) {
- return mService.getIdmapPath(overlayPath, userId);
- }
- }
-
- static void startIdmapService() {
- SystemProperties.set("ctl.start", IDMAP_DAEMON);
- }
-
- static void stopIdmapService() {
- SystemProperties.set("ctl.stop", IDMAP_DAEMON);
- }
-
- private Connection connect() throws Exception {
- synchronized (IDMAP_TOKEN) {
- IoThread.getHandler().removeCallbacksAndMessages(IDMAP_TOKEN);
- if (mService != null) {
- // Not enough time has passed to stop the idmap service. Reuse the existing
- // interface.
- return new Connection();
- }
-
- // Start the idmap service if it is not currently running.
- startIdmapService();
-
- // Block until the service is found.
- FutureTask<IBinder> bindIdmap = new FutureTask<>(() -> {
- IBinder binder = null;
- while (binder == null) {
- try {
- binder = ServiceManager.getService(IDMAP_SERVICE);
- Thread.sleep(100);
- } catch (Exception e) {
- Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not retrieved; "
- + e.getMessage());
- }
- }
- return binder;
- });
-
- IBinder binder;
- try {
- IoThread.getHandler().postAtFrontOfQueue(bindIdmap);
- binder = bindIdmap.get(SERVICE_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (Exception rethrow) {
- Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not found;");
- throw rethrow;
- }
-
- try {
- binder.linkToDeath(() -> {
- Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died");
- }, 0);
- } catch (RemoteException rethrow) {
- Slog.e(TAG, "service '" + IDMAP_SERVICE + "' failed to be bound");
- throw rethrow;
- }
-
- mService = IIdmap2.Stub.asInterface(binder);
- if (DEBUG) {
- Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
- }
-
- return new Connection();
- }
- }
-}
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 9b6d986d90d2..b604aa87f8f3 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -16,6 +16,9 @@
package com.android.server.om;
+import static android.content.Context.IDMAP_SERVICE;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+
import static com.android.server.om.OverlayManagerService.DEBUG;
import static com.android.server.om.OverlayManagerService.TAG;
@@ -24,11 +27,15 @@ import android.content.om.OverlayInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Build.VERSION_CODES;
+import android.os.IBinder;
import android.os.IIdmap2;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Slog;
+import com.android.internal.os.BackgroundThread;
import com.android.server.om.OverlayManagerServiceImpl.PackageManagerHelper;
import com.android.server.pm.Installer;
@@ -44,6 +51,11 @@ import java.io.File;
*/
class IdmapManager {
private static final boolean FEATURE_FLAG_IDMAP2 = true;
+
+ private final Installer mInstaller;
+ private final PackageManagerHelper mPackageManager;
+ private IIdmap2 mIdmap2Service;
+
private static final boolean VENDOR_IS_Q_OR_LATER;
static {
final String value = SystemProperties.get("ro.vndk.version", "29");
@@ -58,14 +70,12 @@ class IdmapManager {
VENDOR_IS_Q_OR_LATER = isQOrLater;
}
- private final Installer mInstaller;
- private final PackageManagerHelper mPackageManager;
- private final IdmapDaemon mIdmapDaemon;
-
IdmapManager(final Installer installer, final PackageManagerHelper packageManager) {
mInstaller = installer;
mPackageManager = packageManager;
- mIdmapDaemon = IdmapDaemon.getInstance();
+ if (FEATURE_FLAG_IDMAP2) {
+ connectToIdmap2d();
+ }
}
boolean createIdmap(@NonNull final PackageInfo targetPackage,
@@ -81,11 +91,11 @@ class IdmapManager {
if (FEATURE_FLAG_IDMAP2) {
int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId);
boolean enforce = enforceOverlayable(overlayPackage);
- if (mIdmapDaemon.verifyIdmap(overlayPath, policies, enforce, userId)) {
+ if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) {
return true;
}
- return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies,
- enforce, userId) != null;
+ return mIdmap2Service.createIdmap(targetPath, overlayPath, policies, enforce,
+ userId) != null;
} else {
mInstaller.idmap(targetPath, overlayPath, sharedGid);
return true;
@@ -103,7 +113,7 @@ class IdmapManager {
}
try {
if (FEATURE_FLAG_IDMAP2) {
- return mIdmapDaemon.removeIdmap(oi.baseCodePath, userId);
+ return mIdmap2Service.removeIdmap(oi.baseCodePath, userId);
} else {
mInstaller.removeIdmap(oi.baseCodePath);
return true;
@@ -127,7 +137,7 @@ class IdmapManager {
final int userId) {
if (FEATURE_FLAG_IDMAP2) {
try {
- return mIdmapDaemon.getIdmapPath(overlayPackagePath, userId);
+ return mIdmap2Service.getIdmapPath(overlayPackagePath, userId);
} catch (Exception e) {
Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": "
+ e.getMessage());
@@ -141,6 +151,35 @@ class IdmapManager {
}
}
+ private void connectToIdmap2d() {
+ IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
+ if (binder != null) {
+ try {
+ binder.linkToDeath(new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died; reconnecting...");
+ connectToIdmap2d();
+ }
+
+ }, 0);
+ } catch (RemoteException e) {
+ binder = null;
+ }
+ }
+ if (binder != null) {
+ mIdmap2Service = IIdmap2.Stub.asInterface(binder);
+ if (DEBUG) {
+ Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
+ }
+ } else {
+ Slog.w(TAG, "service '" + IDMAP_SERVICE + "' not found; trying again...");
+ BackgroundThread.getHandler().postDelayed(() -> {
+ connectToIdmap2d();
+ }, SECOND_IN_MILLIS);
+ }
+ }
+
/**
* Checks if overlayable and policies should be enforced on the specified overlay for backwards
* compatibility with pre-Q overlays.
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index ce951816d3a6..da69986cd59f 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -262,7 +262,6 @@ public final class OverlayManagerService extends SystemService {
initIfNeeded();
onSwitchUser(UserHandle.USER_SYSTEM);
- IdmapDaemon.stopIdmapService();
publishBinderService(Context.OVERLAY_SERVICE, mService);
publishLocalService(OverlayManagerService.class, this);