diff options
5 files changed, 96 insertions, 7 deletions
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt index 326e533df0d8..aeabbd53d177 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt +++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt @@ -46,6 +46,7 @@ import com.android.packageinstaller.common.InstallEventReceiver import com.android.packageinstaller.v2.model.InstallAborted.Companion.ABORT_REASON_DONE import com.android.packageinstaller.v2.model.InstallAborted.Companion.ABORT_REASON_INTERNAL_ERROR import com.android.packageinstaller.v2.model.InstallAborted.Companion.ABORT_REASON_POLICY +import com.android.packageinstaller.v2.model.InstallAborted.Companion.DLG_NONE import com.android.packageinstaller.v2.model.InstallAborted.Companion.DLG_PACKAGE_ERROR import com.android.packageinstaller.v2.model.InstallUserActionRequired.Companion.USER_ACTION_REASON_ANONYMOUS_SOURCE import com.android.packageinstaller.v2.model.InstallUserActionRequired.Companion.USER_ACTION_REASON_INSTALL_CONFIRMATION @@ -283,14 +284,15 @@ class InstallRepository(private val context: Context) { createSessionParams(intent, pfd, uri.toString()) stagedSessionId = packageInstaller.createSession(params) } - } catch (e: IOException) { + } catch (e: Exception) { Log.w(LOG_TAG, "Failed to create a staging session", e) _stagingResult.value = InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Intent.EXTRA_INSTALL_RESULT, PackageManager.INSTALL_FAILED_INVALID_APK ), - activityResultCode = Activity.RESULT_FIRST_USER + activityResultCode = Activity.RESULT_FIRST_USER, + errorDialogType = if (e is IOException) DLG_PACKAGE_ERROR else DLG_NONE ) return } @@ -313,6 +315,14 @@ class InstallRepository(private val context: Context) { ) } } + } else { + _stagingResult.value = InstallAborted( + ABORT_REASON_INTERNAL_ERROR, + resultIntent = Intent().putExtra( + Intent.EXTRA_INSTALL_RESULT, PackageManager.INSTALL_FAILED_INVALID_URI + ), + activityResultCode = Activity.RESULT_FIRST_USER + ) } } diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt index be49b39e9a48..bbb9bca6db51 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt +++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt @@ -122,13 +122,14 @@ data class InstallAborted( */ val resultIntent: Intent? = null, val activityResultCode: Int = Activity.RESULT_CANCELED, - val errorDialogType: Int? = 0, + val errorDialogType: Int? = DLG_NONE, ) : InstallStage(STAGE_ABORTED) { companion object { const val ABORT_REASON_INTERNAL_ERROR = 0 const val ABORT_REASON_POLICY = 1 const val ABORT_REASON_DONE = 2 + const val DLG_NONE = 0 const val DLG_PACKAGE_ERROR = 1 } } diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallActionListener.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallActionListener.kt index c109fc673ec4..1d4d1786c761 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallActionListener.kt +++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallActionListener.kt @@ -34,6 +34,8 @@ interface InstallActionListener { */ fun onNegativeResponse(stageCode: Int) + fun onNegativeResponse(resultCode: Int, data: Intent?) + /** * Launch the intent to open the newly installed / updated app. */ diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt index 2b610d7b06f5..6f8eca3655b5 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt +++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt @@ -36,10 +36,10 @@ import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentManager import androidx.lifecycle.ViewModelProvider import com.android.packageinstaller.R -import com.android.packageinstaller.v2.model.InstallRepository import com.android.packageinstaller.v2.model.InstallAborted import com.android.packageinstaller.v2.model.InstallFailed import com.android.packageinstaller.v2.model.InstallInstalling +import com.android.packageinstaller.v2.model.InstallRepository import com.android.packageinstaller.v2.model.InstallStage import com.android.packageinstaller.v2.model.InstallSuccess import com.android.packageinstaller.v2.model.InstallUserActionRequired @@ -50,6 +50,7 @@ import com.android.packageinstaller.v2.ui.fragments.InstallFailedFragment import com.android.packageinstaller.v2.ui.fragments.InstallInstallingFragment import com.android.packageinstaller.v2.ui.fragments.InstallStagingFragment import com.android.packageinstaller.v2.ui.fragments.InstallSuccessFragment +import com.android.packageinstaller.v2.ui.fragments.ParseErrorFragment import com.android.packageinstaller.v2.ui.fragments.SimpleErrorFragment import com.android.packageinstaller.v2.viewmodel.InstallViewModel import com.android.packageinstaller.v2.viewmodel.InstallViewModelFactory @@ -124,8 +125,15 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { InstallStage.STAGE_ABORTED -> { val aborted = installStage as InstallAborted when (aborted.abortReason) { - InstallAborted.ABORT_REASON_DONE, InstallAborted.ABORT_REASON_INTERNAL_ERROR -> - setResult(aborted.activityResultCode, aborted.resultIntent, true) + InstallAborted.ABORT_REASON_DONE, + InstallAborted.ABORT_REASON_INTERNAL_ERROR -> { + if (aborted.errorDialogType == InstallAborted.DLG_PACKAGE_ERROR) { + val parseErrorDialog = ParseErrorFragment(aborted) + showDialogInner(parseErrorDialog) + } else { + setResult(aborted.activityResultCode, aborted.resultIntent, true) + } + } InstallAborted.ABORT_REASON_POLICY -> showPolicyRestrictionDialog(aborted) else -> setResult(Activity.RESULT_CANCELED, null, true) @@ -204,7 +212,7 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { val blockedByPolicyDialog = createDevicePolicyRestrictionDialog(restriction) // Don't finish the package installer app since the next dialog // will be shown by this app - shouldFinish = blockedByPolicyDialog != null + shouldFinish = blockedByPolicyDialog == null showDialogInner(blockedByPolicyDialog) } setResult(Activity.RESULT_CANCELED, null, shouldFinish) @@ -267,6 +275,10 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { setResult(Activity.RESULT_CANCELED, null, true) } + override fun onNegativeResponse(resultCode: Int, data: Intent?) { + setResult(resultCode, data, true) + } + override fun sendUnknownAppsIntent(sourcePackageName: String) { val settingsIntent = Intent() settingsIntent.setAction(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java new file mode 100644 index 000000000000..68d48d62a0b6 --- /dev/null +++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.packageinstaller.v2.ui.fragments; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.fragment.app.DialogFragment; +import com.android.packageinstaller.R; +import com.android.packageinstaller.v2.model.InstallAborted; +import com.android.packageinstaller.v2.ui.InstallActionListener; + +public class ParseErrorFragment extends DialogFragment { + + private static final String TAG = ParseErrorFragment.class.getSimpleName(); + private final InstallAborted mDialogData; + private InstallActionListener mInstallActionListener; + + public ParseErrorFragment(InstallAborted dialogData) { + mDialogData = dialogData; + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + mInstallActionListener = (InstallActionListener) context; + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) + .setMessage(R.string.Parse_error_dlg_text) + .setPositiveButton(R.string.ok, + (dialog, which) -> + mInstallActionListener.onNegativeResponse( + mDialogData.getActivityResultCode(), mDialogData.getResultIntent())) + .create(); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + mInstallActionListener.onNegativeResponse( + mDialogData.getActivityResultCode(), mDialogData.getResultIntent()); + } +} |