Loading core/java/android/os/incremental/IIncrementalService.aidl +10 −0 Original line number Diff line number Diff line Loading @@ -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); } core/java/android/os/incremental/IStorageHealthListener.aidl +8 −2 Original line number Diff line number Diff line Loading @@ -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); Loading core/java/android/os/incremental/IncrementalManager.java +35 −2 Original line number Diff line number Diff line Loading @@ -283,6 +283,7 @@ public final class IncrementalManager { return; } mLoadingProgressCallbacks.cleanUpCallbacks(storage); unregisterHealthListener(codePath); mService.deleteStorage(storage.getId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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); Loading core/java/android/os/incremental/IncrementalStorage.java +27 −0 Original line number Diff line number Diff line Loading @@ -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; } } } services/core/java/com/android/server/pm/IncrementalStates.java +23 −72 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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 Loading @@ -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) Loading 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()) { Loading @@ -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(); } Loading @@ -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); } /** Loading Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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); } Loading @@ -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
core/java/android/os/incremental/IIncrementalService.aidl +10 −0 Original line number Diff line number Diff line Loading @@ -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); }
core/java/android/os/incremental/IStorageHealthListener.aidl +8 −2 Original line number Diff line number Diff line Loading @@ -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); Loading
core/java/android/os/incremental/IncrementalManager.java +35 −2 Original line number Diff line number Diff line Loading @@ -283,6 +283,7 @@ public final class IncrementalManager { return; } mLoadingProgressCallbacks.cleanUpCallbacks(storage); unregisterHealthListener(codePath); mService.deleteStorage(storage.getId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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); Loading
core/java/android/os/incremental/IncrementalStorage.java +27 −0 Original line number Diff line number Diff line Loading @@ -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; } } }
services/core/java/com/android/server/pm/IncrementalStates.java +23 −72 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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 Loading @@ -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) Loading 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()) { Loading @@ -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(); } Loading @@ -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); } /** Loading Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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); } Loading @@ -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; } }