diff options
4 files changed, 33 insertions, 8 deletions
diff --git a/core/java/android/content/pm/IDataLoaderStatusListener.aidl b/core/java/android/content/pm/IDataLoaderStatusListener.aidl index 24a62c5638ec..efb00a016da5 100644 --- a/core/java/android/content/pm/IDataLoaderStatusListener.aidl +++ b/core/java/android/content/pm/IDataLoaderStatusListener.aidl @@ -40,11 +40,15 @@ oneway interface IDataLoaderStatusListener { /** Installation can't continue as DataLoader failed to stream necessary data. */ const int DATA_LOADER_IMAGE_NOT_READY = 6; + /** DataLoader instance can't run at the moment, but might recover later. + * It's up to system to decide if the app is still usable. */ + const int DATA_LOADER_UNAVAILABLE = 7; + /** 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 = 7; + const int DATA_LOADER_UNRECOVERABLE = 8; /** Data loader status callback */ void onStatusChanged(in int dataLoaderId, in int status); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index d9275f59cbda..9c0ac1884bd5 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -2691,17 +2691,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } break; } + case IDataLoaderStatusListener.DATA_LOADER_UNAVAILABLE: { + // Don't fail or commit the session. Allow caller to commit again. + sendPendingStreaming(mContext, mRemoteStatusReceiver, sessionId, + "DataLoader unavailable"); + break; + } case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE: mDataLoaderFinished = true; dispatchSessionVerificationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE, "DataLoader reported unrecoverable failure."); - return; + break; } } catch (RemoteException e) { // In case of streaming failure we don't want to fail or commit the session. // Just return from this method and allow caller to commit again. sendPendingStreaming(mContext, mRemoteStatusReceiver, sessionId, - new StreamingException(e)); + e.getMessage()); } } }; @@ -3059,13 +3065,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } private static void sendPendingStreaming(Context context, IntentSender target, int sessionId, - Throwable cause) { + @Nullable String cause) { final Intent intent = new Intent(); intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); intent.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_STREAMING); - if (cause != null && !TextUtils.isEmpty(cause.getMessage())) { + if (!TextUtils.isEmpty(cause)) { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, - "Staging Image Not Ready [" + cause.getMessage() + "]"); + "Staging Image Not Ready [" + cause + "]"); } else { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready"); } diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp index 10368586999c..992a4ef76f04 100644 --- a/services/incremental/IncrementalService.cpp +++ b/services/incremental/IncrementalService.cpp @@ -1708,15 +1708,19 @@ bool IncrementalService::DataLoaderStub::setTargetStatus(int newStatus) { { std::unique_lock lock(mStatusMutex); oldStatus = mTargetStatus; - mTargetStatus = newStatus; - mTargetStatusTs = Clock::now(); curStatus = mCurrentStatus; + setTargetStatusLocked(newStatus); } LOG(DEBUG) << "Target status update for DataLoader " << mId << ": " << oldStatus << " -> " << newStatus << " (current " << curStatus << ")"; return fsmStep(); } +void IncrementalService::DataLoaderStub::setTargetStatusLocked(int status) { + mTargetStatus = status; + mTargetStatusTs = Clock::now(); +} + bool IncrementalService::DataLoaderStub::waitForStatus(int status, Clock::duration duration) { auto now = Clock::now(); std::unique_lock lock(mStatusMutex); @@ -1782,6 +1786,9 @@ bool IncrementalService::DataLoaderStub::fsmStep() { } switch (targetStatus) { + case IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE: + // Do nothing, this is a reset state. + break; case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: { return destroy(); } @@ -1796,6 +1803,7 @@ bool IncrementalService::DataLoaderStub::fsmStep() { case IDataLoaderStatusListener::DATA_LOADER_CREATED: switch (currentStatus) { case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: + case IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE: return bind(); case IDataLoaderStatusListener::DATA_LOADER_BOUND: return create(); @@ -1825,9 +1833,15 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount if (mCurrentStatus == newStatus) { return binder::Status::ok(); } + oldStatus = mCurrentStatus; mCurrentStatus = newStatus; targetStatus = mTargetStatus; + + if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE) { + // For unavailable, reset target status. + setTargetStatusLocked(IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE); + } } LOG(DEBUG) << "Current status update for DataLoader " << mId << ": " << oldStatus << " -> " diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h index 81fbe74be606..d5c612daee58 100644 --- a/services/incremental/IncrementalService.h +++ b/services/incremental/IncrementalService.h @@ -187,6 +187,7 @@ private: bool destroy(); bool setTargetStatus(int status); + void setTargetStatusLocked(int status); bool waitForStatus(int status, Clock::duration duration); bool fsmStep(); |