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

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

Merge "[incremental/pm] set health listener on commit and on reboot"

parents 7ae5a974 2570ec01
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -144,4 +144,14 @@ interface IIncrementalService {
     * Stop listening for the loading progress change for a storage.
     */
    boolean unregisterLoadingProgressListener(int storageId);

    /**
     * Register storage health status listener.
     */
    boolean registerStorageHealthListener(int storageId, in StorageHealthCheckParams params, in IStorageHealthListener listener);

    /**
     * Register storage health status listener.
     */
    void unregisterStorageHealthListener(int storageId);
}
+8 −2
Original line number Diff line number Diff line
@@ -26,9 +26,15 @@ oneway interface IStorageHealthListener {
    /** There are reads pending for params.blockedTimeoutMs, waiting till
    *   params.unhealthyTimeoutMs to confirm unhealthy state. */
    const int HEALTH_STATUS_BLOCKED = 2;
    /** There are reads pending for params.unhealthyTimeoutMs>,
    *   marking storage as unhealthy. */
    /** There are reads pending for params.unhealthyTimeoutMs,
    *   marking storage as unhealthy due to unknown issues. */
    const int HEALTH_STATUS_UNHEALTHY = 3;
    /** There are reads pending for params.unhealthyTimeoutMs,
     *  due to data transportation issues. */
    const int HEALTH_STATUS_UNHEALTHY_TRANSPORT = 4;
    /** There are reads pending for params.unhealthyTimeoutMs,
     *  due to limited storage space. */
    const int HEALTH_STATUS_UNHEALTHY_STORAGE = 5;

    /** Health status callback. */
    void onHealthStatus(in int storageId, in int status);
+35 −2
Original line number Diff line number Diff line
@@ -283,6 +283,7 @@ public final class IncrementalManager {
                return;
            }
            mLoadingProgressCallbacks.cleanUpCallbacks(storage);
            unregisterHealthListener(codePath);
            mService.deleteStorage(storage.getId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
@@ -297,7 +298,7 @@ public final class IncrementalManager {
     * @param callback To report loading progress to.
     * @return True if the package name and associated storage id are valid. False otherwise.
     */
    public boolean registerCallback(@NonNull String codePath,
    public boolean registerLoadingProgressCallback(@NonNull String codePath,
            @NonNull IPackageLoadingProgressCallback callback) {
        final IncrementalStorage storage = openStorage(codePath);
        if (storage == null) {
@@ -314,7 +315,7 @@ public final class IncrementalManager {
     * @param codePath Path of the installed package
     * @return True if the package name and associated storage id are valid. False otherwise.
     */
    public boolean unregisterCallback(@NonNull String codePath,
    public boolean unregisterLoadingProgressCallback(@NonNull String codePath,
            @NonNull IPackageLoadingProgressCallback callback) {
        final IncrementalStorage storage = openStorage(codePath);
        if (storage == null) {
@@ -414,6 +415,38 @@ public final class IncrementalManager {
        }
    }

    /**
     * Specify the health check params and listener for listening to Incremental Storage health
     * status changes. Notice that this will overwrite the previously registered listener.
     * @param codePath Path of the installed package. This path is on an Incremental Storage.
     * @param healthCheckParams The params for health state change timeouts.
     * @param listener To report health status change.
     * @return True if listener was successfully registered.
     */
    public boolean registerHealthListener(@NonNull String codePath,
            @NonNull StorageHealthCheckParams healthCheckParams,
            @NonNull IStorageHealthListener.Stub listener) {
        final IncrementalStorage storage = openStorage(codePath);
        if (storage == null) {
            // storage does not exist, package not installed
            return false;
        }
        return storage.registerStorageHealthListener(healthCheckParams, listener);
    }

    /**
     * Stop listening to health status changes on an Incremental Storage.
     * @param codePath Path of the installed package. This path is on an Incremental Storage.
     */
    public void unregisterHealthListener(@NonNull String codePath) {
        final IncrementalStorage storage = openStorage(codePath);
        if (storage == null) {
            // storage does not exist, package not installed
            return;
        }
        storage.unregisterStorageHealthListener();
    }

    /* Native methods */
    private static native boolean nativeIsEnabled();
    private static native boolean nativeIsIncrementalPath(@NonNull String path);
+27 −0
Original line number Diff line number Diff line
@@ -545,4 +545,31 @@ public final class IncrementalStorage {
            return false;
        }
    }

    /**
     * Register to listen to the status changes of the storage health.
     * @param healthCheckParams Params to specify status change timeouts.
     * @param listener To report health status change from Incremental Service to the caller.
     */
    public boolean registerStorageHealthListener(StorageHealthCheckParams healthCheckParams,
            IStorageHealthListener listener) {
        try {
            return mService.registerStorageHealthListener(mId, healthCheckParams, listener);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            return false;
        }
    }

    /**
     * Stops listening to the status changes of the storage health.
     */
    public void unregisterStorageHealthListener() {
        try {
            mService.unregisterStorageHealthListener(mId);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            return;
        }
    }
}
+23 −72
Original line number Diff line number Diff line
@@ -16,18 +16,21 @@

package com.android.server.pm;

import android.content.pm.IDataLoaderStatusListener;
import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_OK;
import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY;
import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_STORAGE;
import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_TRANSPORT;

import android.content.pm.IncrementalStatesInfo;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.incremental.IStorageHealthListener;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.function.pooled.PooledLambda;

import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * Manages state transitions of a package installed on Incremental File System. Currently manages:
@@ -36,8 +39,7 @@ import java.util.function.BiConsumer;
 *
 * The following events might change the states of a package:
 * 1. Installation commit
 * 2. Incremental storage health
 * 3. Data loader stream health
 * 2. Incremental storage health changes
 * 4. Loading progress changes
 *
 * @hide
@@ -48,16 +50,14 @@ public final class IncrementalStates {
    private final Handler mHandler = BackgroundThread.getHandler();
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private int mStreamStatus = IDataLoaderStatusListener.STREAM_HEALTHY;
    @GuardedBy("mLock")
    private int mStorageHealthStatus = IStorageHealthListener.HEALTH_STATUS_OK;
    private int mStorageHealthStatus = HEALTH_STATUS_OK;
    @GuardedBy("mLock")
    private final LoadingState mLoadingState;
    @GuardedBy("mLock")
    private StartableState mStartableState;
    @GuardedBy("mLock")
    private Callback mCallback = null;
    private final BiConsumer<Integer, Integer> mStatusConsumer;
    private final Consumer<Integer> mStatusConsumer;

    public IncrementalStates() {
        // By default the package is not startable and not fully loaded (i.e., is loading)
@@ -148,12 +148,9 @@ public final class IncrementalStates {
        }
    }

    private class StatusConsumer implements BiConsumer<Integer, Integer> {
    private class StatusConsumer implements Consumer<Integer> {
        @Override
        public void accept(Integer streamStatus, Integer storageStatus) {
            if (streamStatus == null && storageStatus == null) {
                return;
            }
        public void accept(Integer storageStatus) {
            final boolean oldState, newState;
            synchronized (mLock) {
                if (!mLoadingState.isLoading()) {
@@ -161,12 +158,7 @@ public final class IncrementalStates {
                    return;
                }
                oldState = mStartableState.isStartable();
                if (streamStatus != null) {
                    mStreamStatus = (Integer) streamStatus;
                }
                if (storageStatus != null) {
                    mStorageHealthStatus = (Integer) storageStatus;
                }
                mStorageHealthStatus = storageStatus;
                updateStartableStateLocked();
                newState = mStartableState.isStartable();
            }
@@ -188,21 +180,7 @@ public final class IncrementalStates {
            Slog.i(TAG, "received storage health status changed event : storageHealthStatus="
                    + storageHealthStatus);
        }
        mStatusConsumer.accept(null, storageHealthStatus);
    }

    /**
     * By calling this method, the caller indicates that the stream status of the package has
     * been
     * changed. This could indicate a streaming error. The state will change according to the
     * status
     * code defined in {@code IDataLoaderStatusListener}.
     */
    public void onStreamStatusChanged(int streamState) {
        if (DEBUG) {
            Slog.i(TAG, "received stream status changed event : streamState=" + streamState);
        }
        mStatusConsumer.accept(streamState, null);
        mStatusConsumer.accept(storageHealthStatus);
    }

    /**
@@ -284,35 +262,16 @@ public final class IncrementalStates {
        final boolean currentState = mStartableState.isStartable();
        boolean nextState = currentState;
        if (!currentState) {
            if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_OK
                    && mStreamStatus == IDataLoaderStatusListener.STREAM_HEALTHY) {
                // change from unstartable -> startable when both stream and storage are healthy
            if (mStorageHealthStatus == HEALTH_STATUS_OK) {
                // change from unstartable -> startable
                nextState = true;
            }
        } else {
            if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_UNHEALTHY) {
                // unrecoverable if storage is unhealthy
            if (mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY
                    || mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY_STORAGE
                    || mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY_TRANSPORT) {
                // change from startable -> unstartable
                nextState = false;
            } else {
                switch (mStreamStatus) {
                    case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
                        // unrecoverable, fall through
                    case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
                        // unrecoverable
                        nextState = false;
                        break;
                    }
                    case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
                        if (mStorageHealthStatus != IStorageHealthListener.HEALTH_STATUS_OK) {
                            // unrecoverable if there is a pending read AND storage is limited
                            nextState = false;
                        }
                        break;
                    }
                    default:
                        // anything else, remain startable
                        break;
                }
            }
        }
        if (nextState == currentState) {
@@ -370,17 +329,11 @@ public final class IncrementalStates {
                return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
            }
            // Translate stream status to reason for unstartable state
            switch (mStreamStatus) {
                case IDataLoaderStatusListener.STREAM_TRANSPORT_ERROR:
                    // fall through
                case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
                    // fall through
                case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
                    return PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR;
                }
                case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
            switch (mStorageHealthStatus) {
                case HEALTH_STATUS_UNHEALTHY_STORAGE:
                    return PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE;
                }
                case HEALTH_STATUS_UNHEALTHY_TRANSPORT:
                    return PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR;
                default:
                    return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
            }
@@ -464,7 +417,6 @@ public final class IncrementalStates {
        }
        IncrementalStates l = (IncrementalStates) o;
        return l.mStorageHealthStatus == mStorageHealthStatus
                && l.mStreamStatus == mStreamStatus
                && l.mStartableState.equals(mStartableState)
                && l.mLoadingState.equals(mLoadingState);
    }
@@ -474,7 +426,6 @@ public final class IncrementalStates {
        int hashCode = mStartableState.hashCode();
        hashCode = 31 * hashCode + mLoadingState.hashCode();
        hashCode = 31 * hashCode + mStorageHealthStatus;
        hashCode = 31 * hashCode + mStreamStatus;
        return hashCode;
    }
}
Loading