1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.packageinstaller.v2.model 18 19 import android.app.Activity 20 import android.content.Intent 21 import android.content.pm.PackageManager 22 import android.graphics.drawable.Drawable 23 24 sealed class InstallStage(val stageCode: Int) { 25 26 companion object { 27 const val STAGE_DEFAULT = -1 28 const val STAGE_ABORTED = 0 29 const val STAGE_STAGING = 1 30 const val STAGE_READY = 2 31 const val STAGE_USER_ACTION_REQUIRED = 3 32 const val STAGE_INSTALLING = 4 33 const val STAGE_SUCCESS = 5 34 const val STAGE_FAILED = 6 35 } 36 } 37 38 class InstallStaging : InstallStage(STAGE_STAGING) 39 40 class InstallReady : InstallStage(STAGE_READY) 41 42 data class InstallUserActionRequired( 43 val actionReason: Int, 44 private val appSnippet: PackageUtil.AppSnippet? = null, 45 val isAppUpdating: Boolean = false, 46 val dialogMessage: String? = null, 47 ) : InstallStage(STAGE_USER_ACTION_REQUIRED) { 48 49 val appIcon: Drawable? 50 get() = appSnippet?.icon 51 52 val appLabel: String? <lambda>null53 get() = appSnippet?.let { appSnippet.label as String? } 54 55 companion object { 56 const val USER_ACTION_REASON_UNKNOWN_SOURCE = 0 57 const val USER_ACTION_REASON_ANONYMOUS_SOURCE = 1 58 const val USER_ACTION_REASON_INSTALL_CONFIRMATION = 2 59 } 60 } 61 62 data class InstallInstalling(private val appSnippet: PackageUtil.AppSnippet) : 63 InstallStage(STAGE_INSTALLING) { 64 65 val appIcon: Drawable? 66 get() = appSnippet.icon 67 68 val appLabel: String? 69 get() = appSnippet.label as String? 70 } 71 72 data class InstallSuccess( 73 private val appSnippet: PackageUtil.AppSnippet, 74 val shouldReturnResult: Boolean = false, 75 /** 76 * 77 * * If the caller is requesting a result back, this will hold the Intent with 78 * [Intent.EXTRA_INSTALL_RESULT] set to [PackageManager.INSTALL_SUCCEEDED] which is sent 79 * back to the caller. 80 * 81 * * If the caller doesn't want the result back, this will hold the Intent that launches 82 * the newly installed / updated app if a launchable activity exists. 83 */ 84 val resultIntent: Intent? = null, 85 ) : InstallStage(STAGE_SUCCESS) { 86 87 val appIcon: Drawable? 88 get() = appSnippet.icon 89 90 val appLabel: String? 91 get() = appSnippet.label as String? 92 } 93 94 data class InstallFailed( 95 private val appSnippet: PackageUtil.AppSnippet, 96 val legacyCode: Int, 97 val statusCode: Int, 98 val message: String?, 99 ) : InstallStage(STAGE_FAILED) { 100 101 val appIcon: Drawable? 102 get() = appSnippet.icon 103 104 val appLabel: String? 105 get() = appSnippet.label as String? 106 } 107 108 data class InstallAborted( 109 val abortReason: Int, 110 /** 111 * It will hold the restriction name, when the restriction was enforced by the system, and not 112 * a device admin. 113 */ 114 val message: String? = null, 115 /** 116 * * If abort reason is [ABORT_REASON_POLICY], then this will hold the Intent 117 * to display a support dialog when a feature was disabled by an admin. It will be 118 * `null` if the feature is disabled by the system. In this case, the restriction name 119 * will be set in [message] 120 * * If the abort reason is [ABORT_REASON_INTERNAL_ERROR], it **may** hold an 121 * intent to be sent as a result to the calling activity. 122 */ 123 val resultIntent: Intent? = null, 124 val activityResultCode: Int = Activity.RESULT_CANCELED, 125 val errorDialogType: Int? = DLG_NONE, 126 ) : InstallStage(STAGE_ABORTED) { 127 128 companion object { 129 const val ABORT_REASON_INTERNAL_ERROR = 0 130 const val ABORT_REASON_POLICY = 1 131 const val ABORT_REASON_DONE = 2 132 const val DLG_NONE = 0 133 const val DLG_PACKAGE_ERROR = 1 134 } 135 } 136