[incfs] Cleanup data loader connection and fds in Java
Bug: 153704006
Test: atest PackageManagerShellCommandTest \
PackageManagerShellCommandIncrementalTest \
IncrementalServiceTest
Change-Id: I8749480297c5afc2a25da160643b58c6be8b6d34
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index ae9c384..062e9e1 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -38,6 +38,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
+import libcore.io.IoUtils;
+
import java.util.List;
/**
@@ -64,31 +66,52 @@
publishBinderService(Context.DATA_LOADER_MANAGER_SERVICE, mBinderService);
}
+ private static void closeQuietly(FileSystemControlParcel control) {
+ if (control == null || control.incremental == null) {
+ return;
+ }
+ IoUtils.closeQuietly(control.incremental.cmd);
+ IoUtils.closeQuietly(control.incremental.pendingReads);
+ IoUtils.closeQuietly(control.incremental.log);
+ }
+
final class DataLoaderManagerBinderService extends IDataLoaderManager.Stub {
@Override
public boolean initializeDataLoader(int dataLoaderId, DataLoaderParamsParcel params,
FileSystemControlParcel control, IDataLoaderStatusListener listener) {
- synchronized (mLock) {
- if (mServiceConnections.get(dataLoaderId) != null) {
- Slog.e(TAG, "Data loader of ID=" + dataLoaderId + " already exists.");
+ DataLoaderServiceConnection connection = null;
+ try {
+ synchronized (mLock) {
+ if (mServiceConnections.get(dataLoaderId) != null) {
+ Slog.e(TAG, "Data loader of ID=" + dataLoaderId + " already exists.");
+ return false;
+ }
+ }
+ ComponentName componentName =
+ new ComponentName(params.packageName, params.className);
+ ComponentName dataLoaderComponent = resolveDataLoaderComponentName(componentName);
+ if (dataLoaderComponent == null) {
return false;
}
- }
- ComponentName componentName = new ComponentName(params.packageName, params.className);
- ComponentName dataLoaderComponent = resolveDataLoaderComponentName(componentName);
- if (dataLoaderComponent == null) {
- return false;
- }
- // Binds to the specific data loader service
- DataLoaderServiceConnection connection =
- new DataLoaderServiceConnection(dataLoaderId, params, control, listener);
- Intent intent = new Intent();
- intent.setComponent(dataLoaderComponent);
- if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
- UserHandle.of(UserHandle.getCallingUserId()))) {
- Slog.e(TAG, "Failed to bind to data loader binder service.");
- mContext.unbindService(connection);
- return false;
+ // Binds to the specific data loader service
+ connection =
+ new DataLoaderServiceConnection(dataLoaderId, params,
+ control, listener);
+ control = null; // now connection manages it
+ Intent intent = new Intent();
+ intent.setComponent(dataLoaderComponent);
+ if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
+ UserHandle.of(UserHandle.getCallingUserId()))) {
+ Slog.e(TAG, "Failed to bind to data loader binder service.");
+ mContext.unbindService(connection);
+ return false;
+ }
+ connection = null;
+ } finally {
+ DataLoaderManagerService.closeQuietly(control);
+ if (connection != null) {
+ connection.close();
+ }
}
return true;
}
@@ -173,7 +196,7 @@
}
}
- class DataLoaderServiceConnection implements ServiceConnection {
+ class DataLoaderServiceConnection implements ServiceConnection, AutoCloseable {
final int mId;
final DataLoaderParamsParcel mParams;
final FileSystemControlParcel mControl;
@@ -204,15 +227,34 @@
@Override
public void onServiceDisconnected(ComponentName arg0) {
- if (mListener != null) {
- try {
- mListener.onStatusChanged(mId, IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
- } catch (RemoteException ignored) {
- }
- }
+ Slog.i(TAG, "DataLoader " + mId + " disconnected, but will try to recover");
+ callListener(IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
remove();
}
+ @Override
+ public void onBindingDied(ComponentName name) {
+ Slog.i(TAG, "DataLoader " + mId + " died");
+ callListener(IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
+ mContext.unbindService(this);
+ close();
+ remove();
+ }
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ Slog.i(TAG, "DataLoader " + mId + " failed to start");
+ callListener(IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
+ mContext.unbindService(this);
+ close();
+ remove();
+ }
+
+ @Override
+ public void close() {
+ DataLoaderManagerService.closeQuietly(mControl);
+ }
+
IDataLoader getDataLoader() {
return mDataLoader;
}
@@ -223,6 +265,8 @@
} catch (RemoteException ignored) {
}
mContext.unbindService(this);
+ close();
+ remove();
}
private void remove() {
@@ -230,5 +274,14 @@
mServiceConnections.remove(mId);
}
}
+
+ private void callListener(int status) {
+ if (mListener != null) {
+ try {
+ mListener.onStatusChanged(mId, status);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
}
}