Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a721ccdc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "bound status" into rvc-dev

* changes:
  DataLoader cleanup: return plain FD from Java.
  Keep only service binding in DataLoaderManager.
parents e0e595d2 b3e7e297
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -41,17 +41,16 @@ public class DataLoaderManager {
     * @param dataLoaderId ID for the new data loader binder service.
     * @param params       DataLoaderParamsParcel object that contains data loader params, including
     *                     its package name, class name, and additional parameters.
     * @param control      FileSystemControlParcel that contains filesystem control handlers.
     * @param listener     Callback for the data loader service to report status back to the
     *                     caller.
     * @return false if 1) target ID collides with a data loader that is already bound to data
     * loader manager; 2) package name is not specified; 3) fails to find data loader package;
     * or 4) fails to bind to the specified data loader service, otherwise return true.
     */
    public boolean initializeDataLoader(int dataLoaderId, @NonNull DataLoaderParamsParcel params,
            @NonNull FileSystemControlParcel control, @NonNull IDataLoaderStatusListener listener) {
    public boolean bindToDataLoader(int dataLoaderId, @NonNull DataLoaderParamsParcel params,
            @NonNull IDataLoaderStatusListener listener) {
        try {
            return mService.initializeDataLoader(dataLoaderId, params, control, listener);
            return mService.bindToDataLoader(dataLoaderId, params, listener);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -70,12 +69,13 @@ public class DataLoaderManager {
    }

    /**
     * Destroys the data loader binder service and removes it from data loader manager service.
     * Unbinds from a data loader binder service, specified by its ID.
     * DataLoader will receive destroy notification.
     */
    @Nullable
    public void destroyDataLoader(int dataLoaderId) {
    public void unbindFromDataLoader(int dataLoaderId) {
        try {
            mService.destroyDataLoader(dataLoaderId);
            mService.unbindFromDataLoader(dataLoaderId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+4 −4
Original line number Diff line number Diff line
@@ -23,8 +23,8 @@ import android.content.pm.IDataLoaderStatusListener;

/** @hide */
interface IDataLoaderManager {
    boolean initializeDataLoader(int id, in DataLoaderParamsParcel params,
            in FileSystemControlParcel control, IDataLoaderStatusListener listener);
    boolean bindToDataLoader(int id, in DataLoaderParamsParcel params,
            IDataLoaderStatusListener listener);
    IDataLoader getDataLoader(int dataLoaderId);
    void destroyDataLoader(int dataLoaderId);
    void unbindFromDataLoader(int dataLoaderId);
}
+11 −11
Original line number Diff line number Diff line
@@ -21,30 +21,30 @@ package android.content.pm;
 * @hide
 */
oneway interface IDataLoaderStatusListener {
    /** When this status is returned from DataLoader, it means that the DataLoader
    *   process is running, bound to and has handled onCreate(). */
    const int DATA_LOADER_CREATED = 0;
    /** Listener will receive this status when the DataLoader process died,
    *   binder disconnected or class destroyed. */
    const int DATA_LOADER_DESTROYED = 1;
    /** The DataLoader process died, binder disconnected or class destroyed. */
    const int DATA_LOADER_DESTROYED = 0;
    /** DataLoader process is running and bound to. */
    const int DATA_LOADER_BOUND = 1;
    /** DataLoader has handled onCreate(). */
    const int DATA_LOADER_CREATED = 2;

    /** DataLoader can receive missing pages and read pages notifications,
     *  and ready to provide data. */
    const int DATA_LOADER_STARTED = 2;
    const int DATA_LOADER_STARTED = 3;
    /** DataLoader no longer ready to provide data and is not receiving
    *   any notifications from IncFS. */
    const int DATA_LOADER_STOPPED = 3;
    const int DATA_LOADER_STOPPED = 4;

    /** DataLoader streamed everything necessary to continue installation. */
    const int DATA_LOADER_IMAGE_READY = 4;
    const int DATA_LOADER_IMAGE_READY = 5;
    /** Installation can't continue as DataLoader failed to stream necessary data. */
    const int DATA_LOADER_IMAGE_NOT_READY = 5;
    const int DATA_LOADER_IMAGE_NOT_READY = 6;

    /** DataLoader reports that this instance is invalid and can never be restored.
    *   Warning: this is a terminal status that data loader should use carefully and
    *            the system should almost never use - e.g. only if all recovery attempts
    *            fail and all retry limits are exceeded. */
    const int DATA_LOADER_UNRECOVERABLE = 6;
    const int DATA_LOADER_UNRECOVERABLE = 7;

    /** Data loader status callback */
    void onStatusChanged(in int dataLoaderId, in int status);
+53 −84
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderManager;
import android.content.pm.IDataLoaderStatusListener;
@@ -35,11 +34,8 @@ import android.os.UserHandle;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;

import libcore.io.IoUtils;

import java.util.List;

/**
@@ -51,8 +47,6 @@ public class DataLoaderManagerService extends SystemService {
    private static final String TAG = "DataLoaderManager";
    private final Context mContext;
    private final DataLoaderManagerBinderService mBinderService;
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private SparseArray<DataLoaderServiceConnection> mServiceConnections = new SparseArray<>();

    public DataLoaderManagerService(Context context) {
@@ -66,53 +60,35 @@ public class DataLoaderManagerService extends SystemService {
        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) {
            DataLoaderServiceConnection connection = null;
            try {
                synchronized (mLock) {
        public boolean bindToDataLoader(int dataLoaderId, DataLoaderParamsParcel params,
                IDataLoaderStatusListener listener) {
            synchronized (mServiceConnections) {
                if (mServiceConnections.get(dataLoaderId) != null) {
                        Slog.e(TAG, "Data loader of ID=" + dataLoaderId + " already exists.");
                        return false;
                    return true;
                }
            }
                ComponentName componentName =
                        new ComponentName(params.packageName, params.className);
            ComponentName componentName = new ComponentName(params.packageName, params.className);
            ComponentName dataLoaderComponent = resolveDataLoaderComponentName(componentName);
            if (dataLoaderComponent == null) {
                Slog.e(TAG, "Invalid component: " + componentName + " for ID=" + dataLoaderId);
                return false;
            }
                // Binds to the specific data loader service
                connection =
                        new DataLoaderServiceConnection(dataLoaderId, params,
                                                        control, listener);
                control = null; // now connection manages it

            // Binds to the specific data loader service.
            DataLoaderServiceConnection connection = new DataLoaderServiceConnection(dataLoaderId,
                    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.");
                Slog.e(TAG,
                        "Failed to bind to: " + dataLoaderComponent + " for ID=" + dataLoaderId);
                mContext.unbindService(connection);
                return false;
            }
                connection = null;
            } finally {
                DataLoaderManagerService.closeQuietly(control);
                if (connection != null) {
                    connection.close();
                }
            }
            return true;
        }

@@ -169,7 +145,7 @@ public class DataLoaderManagerService extends SystemService {
         */
        @Override
        public @Nullable IDataLoader getDataLoader(int dataLoaderId) {
            synchronized (mLock) {
            synchronized (mServiceConnections) {
                DataLoaderServiceConnection serviceConnection = mServiceConnections.get(
                        dataLoaderId, null);
                if (serviceConnection == null) {
@@ -180,14 +156,14 @@ public class DataLoaderManagerService extends SystemService {
        }

        /**
         * Destroys a data loader binder service, specified by its ID.
         * Unbinds from a data loader binder service, specified by its ID. DataLoader will receive
         * destroy notification.
         */
        @Override
        public void destroyDataLoader(int dataLoaderId) {
            synchronized (mLock) {
        public void unbindFromDataLoader(int dataLoaderId) {
            synchronized (mServiceConnections) {
                DataLoaderServiceConnection serviceConnection = mServiceConnections.get(
                        dataLoaderId, null);

                if (serviceConnection == null) {
                    return;
                }
@@ -196,18 +172,13 @@ public class DataLoaderManagerService extends SystemService {
        }
    }

    class DataLoaderServiceConnection implements ServiceConnection, AutoCloseable {
    private class DataLoaderServiceConnection implements ServiceConnection {
        final int mId;
        final DataLoaderParamsParcel mParams;
        final FileSystemControlParcel mControl;
        final IDataLoaderStatusListener mListener;
        IDataLoader mDataLoader;

        DataLoaderServiceConnection(int id, DataLoaderParamsParcel params,
                FileSystemControlParcel control, IDataLoaderStatusListener listener) {
        DataLoaderServiceConnection(int id, IDataLoaderStatusListener listener) {
            mId = id;
            mParams = params;
            mControl = control;
            mListener = listener;
            mDataLoader = null;
        }
@@ -215,44 +186,40 @@ public class DataLoaderManagerService extends SystemService {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            mDataLoader = IDataLoader.Stub.asInterface(service);
            synchronized (mLock) {
                mServiceConnections.append(mId, this);
            if (mDataLoader == null) {
                onNullBinding(className);
                return;
            }
            try {
                mDataLoader.create(mId, mParams, mControl, mListener);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to create data loader service.", e);
            synchronized (mServiceConnections) {
                if (mServiceConnections.get(mId) != null) {
                    // Another connection already bound for this ID.
                    mContext.unbindService(this);
                    return;
                }
                mServiceConnections.append(mId, this);
            }
            callListener(IDataLoaderStatusListener.DATA_LOADER_BOUND);
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            Slog.i(TAG, "DataLoader " + mId + " disconnected, but will try to recover");
            callListener(IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
            remove();
            destroy();
        }

        @Override
        public void onBindingDied(ComponentName name) {
            Slog.i(TAG, "DataLoader " + mId + " died");
            callListener(IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
            mContext.unbindService(this);
            close();
            remove();
            destroy();
        }

        @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);
            destroy();
        }

        IDataLoader getDataLoader() {
@@ -260,17 +227,19 @@ public class DataLoaderManagerService extends SystemService {
        }

        void destroy() {
            if (mDataLoader != null) {
                try {
                    mDataLoader.destroy(mId);
                } catch (RemoteException ignored) {
                }
                mDataLoader = null;
            }
            mContext.unbindService(this);
            close();
            remove();
        }

        private void remove() {
            synchronized (mLock) {
            synchronized (mServiceConnections) {
                mServiceConnections.remove(mId);
            }
        }
+15 −10
Original line number Diff line number Diff line
@@ -2601,8 +2601,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    "Failed to find data loader manager service");
        }

        final DataLoaderParams params = this.params.dataLoaderParams;
        final boolean manualStartAndDestroy = !isIncrementalInstallation();
        IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
        final IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
            @Override
            public void onStatusChanged(int dataLoaderId, int status) {
                switch (status) {
@@ -2629,6 +2630,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    }

                    switch (status) {
                        case IDataLoaderStatusListener.DATA_LOADER_BOUND: {
                            if (manualStartAndDestroy) {
                                FileSystemControlParcel control = new FileSystemControlParcel();
                                control.callback = new FileSystemConnector(addedFiles);
                                dataLoader.create(dataLoaderId, params.getData(), control, this);
                            }

                            break;
                        }
                        case IDataLoaderStatusListener.DATA_LOADER_CREATED: {
                            if (manualStartAndDestroy) {
                                // IncrementalFileStorages will call start after all files are
@@ -2680,8 +2690,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

        if (!manualStartAndDestroy) {
            try {
                mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext,
                        stageDir, params.dataLoaderParams, listener, addedFiles);
                mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext, stageDir,
                        params, listener, addedFiles);
                return false;
            } catch (IOException e) {
                throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, e.getMessage(),
@@ -2689,13 +2699,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            }
        }

        final FileSystemConnector connector = new FileSystemConnector(addedFiles);
        final FileSystemControlParcel control = new FileSystemControlParcel();
        control.callback = connector;

        final DataLoaderParams params = this.params.dataLoaderParams;
        if (!dataLoaderManager.initializeDataLoader(
                sessionId, params.getData(), control, listener)) {
        if (!dataLoaderManager.bindToDataLoader(
                sessionId, params.getData(), listener)) {
            throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
                    "Failed to initialize data loader");
        }
Loading