Merge "Decouple FUSE mount from main thread for demo user" into rvc-dev am: 931d7d2703

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12261202

Change-Id: Ifc957093c96f71273939e8f1bab5013ad9d0b506
This commit is contained in:
TreeHugger Robot
2020-07-29 22:06:05 +00:00
committed by Automerger Merge Worker

View File

@@ -29,6 +29,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.Bundle; import android.os.Bundle;
import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.ParcelableException; import android.os.ParcelableException;
@@ -64,9 +65,6 @@ public final class StorageUserConnection {
private static final String TAG = "StorageUserConnection"; private static final String TAG = "StorageUserConnection";
private static final int DEFAULT_REMOTE_TIMEOUT_SECONDS = 20; private static final int DEFAULT_REMOTE_TIMEOUT_SECONDS = 20;
// TODO(b/161702661): Workaround for demo user to have shorter timeout.
// This allows the DevicePolicyManagerService#enableSystemApp call to succeed without ANR.
private static final int DEMO_USER_REMOTE_TIMEOUT_SECONDS = 5;
private final Object mLock = new Object(); private final Object mLock = new Object();
private final Context mContext; private final Context mContext;
@@ -75,6 +73,7 @@ public final class StorageUserConnection {
private final ActiveConnection mActiveConnection = new ActiveConnection(); private final ActiveConnection mActiveConnection = new ActiveConnection();
private final boolean mIsDemoUser; private final boolean mIsDemoUser;
@GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>(); @GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>();
@GuardedBy("mLock") @Nullable private HandlerThread mHandlerThread;
public StorageUserConnection(Context context, int userId, StorageSessionController controller) { public StorageUserConnection(Context context, int userId, StorageSessionController controller) {
mContext = Objects.requireNonNull(context); mContext = Objects.requireNonNull(context);
@@ -82,6 +81,10 @@ public final class StorageUserConnection {
mSessionController = controller; mSessionController = controller;
mIsDemoUser = LocalServices.getService(UserManagerInternal.class) mIsDemoUser = LocalServices.getService(UserManagerInternal.class)
.getUserInfo(userId).isDemo(); .getUserInfo(userId).isDemo();
if (mIsDemoUser) {
mHandlerThread = new HandlerThread("StorageUserConnectionThread-" + mUserId);
mHandlerThread.start();
}
} }
/** /**
@@ -188,6 +191,9 @@ public final class StorageUserConnection {
*/ */
public void close() { public void close() {
mActiveConnection.close(); mActiveConnection.close();
if (mIsDemoUser) {
mHandlerThread.quit();
}
} }
/** Returns all created sessions. */ /** Returns all created sessions. */
@@ -207,8 +213,7 @@ public final class StorageUserConnection {
private void waitForLatch(CountDownLatch latch, String reason) throws TimeoutException { private void waitForLatch(CountDownLatch latch, String reason) throws TimeoutException {
try { try {
if (!latch.await(mIsDemoUser ? DEMO_USER_REMOTE_TIMEOUT_SECONDS if (!latch.await(DEFAULT_REMOTE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
: DEFAULT_REMOTE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
// TODO(b/140025078): Call ActivityManager ANR API? // TODO(b/140025078): Call ActivityManager ANR API?
Slog.wtf(TAG, "Failed to bind to the ExternalStorageService for user " + mUserId); Slog.wtf(TAG, "Failed to bind to the ExternalStorageService for user " + mUserId);
throw new TimeoutException("Latch wait for " + reason + " elapsed"); throw new TimeoutException("Latch wait for " + reason + " elapsed");
@@ -424,15 +429,32 @@ public final class StorageUserConnection {
}; };
Slog.i(TAG, "Binding to the ExternalStorageService for user " + mUserId); Slog.i(TAG, "Binding to the ExternalStorageService for user " + mUserId);
if (mContext.bindServiceAsUser(new Intent().setComponent(name), mServiceConnection, if (mIsDemoUser) {
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, // Schedule on a worker thread for demo user to avoid deadlock
UserHandle.of(mUserId))) { if (mContext.bindServiceAsUser(new Intent().setComponent(name),
Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId); mServiceConnection,
return mLatch; Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
mHandlerThread.getThreadHandler(),
UserHandle.of(mUserId))) {
Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId);
return mLatch;
} else {
mIsConnecting = false;
throw new ExternalStorageServiceException(
"Failed to bind to the ExternalStorageService for user " + mUserId);
}
} else { } else {
mIsConnecting = false; if (mContext.bindServiceAsUser(new Intent().setComponent(name),
throw new ExternalStorageServiceException( mServiceConnection,
"Failed to bind to the ExternalStorageService for user " + mUserId); Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.of(mUserId))) {
Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId);
return mLatch;
} else {
mIsConnecting = false;
throw new ExternalStorageServiceException(
"Failed to bind to the ExternalStorageService for user " + mUserId);
}
} }
} }
} }