Loading packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt +41 −16 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.packageinstaller.v2.model.PackageUtil.getPackageNameForUid import com.android.packageinstaller.v2.model.PackageUtil.isCallerSessionOwner import com.android.packageinstaller.v2.model.PackageUtil.isInstallPermissionGrantedOrRequested import com.android.packageinstaller.v2.model.PackageUtil.isPermissionGranted import com.android.packageinstaller.v2.model.PackageUtil.localLogv import java.io.File import java.io.IOException import kotlinx.coroutines.DelicateCoroutinesApi Loading @@ -75,7 +76,6 @@ class InstallRepository(private val context: Context) { private val devicePolicyManager: DevicePolicyManager? = context.getSystemService(DevicePolicyManager::class.java) private val appOpsManager: AppOpsManager? = context.getSystemService(AppOpsManager::class.java) private val localLOGV = false private var isSessionInstall = false private var isTrustedSource = false private val _stagingResult = MutableLiveData<InstallStage>() Loading Loading @@ -155,8 +155,18 @@ class InstallRepository(private val context: Context) { originatingUid, callingAttributionTag ) if(localLogv) { Log.i(LOG_TAG, "Intent: $intent\n" + "sessionId: $sessionId\n" + "staged sessionId: $stagedSessionId\n" + "calling package: $callingPackage\n" + "callingUid: $callingUid\n" + "originatingUid: $originatingUid") } if (callingUid == Process.INVALID_UID && sourceInfo == null) { // Caller's identity could not be determined. Abort the install Log.e(LOG_TAG, "Cannot determine caller since UID is invalid and sourceInfo is null") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } Loading @@ -165,6 +175,9 @@ class InstallRepository(private val context: Context) { || (stagedSessionId != SessionInfo.INVALID_ID && !isCallerSessionOwner(packageInstaller, Process.myUid(), stagedSessionId)) ) { Log.e(LOG_TAG, "UID is not the owner of the session:\n" + "CallingUid: $originatingUid | SessionId: $sessionId\n" + "My UID: ${Process.myUid()} | StagedSessionId: $stagedSessionId") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } Loading @@ -173,6 +186,9 @@ class InstallRepository(private val context: Context) { context, callingUid, originatingUid, isTrustedSource ) ) { Log.e(LOG_TAG, "UID $originatingUid needs to declare " + Manifest.permission.REQUEST_INSTALL_PACKAGES ) return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } Loading @@ -180,6 +196,7 @@ class InstallRepository(private val context: Context) { if (restriction != null) { val adminSupportDetailsIntent = devicePolicyManager!!.createAdminSupportIntent(restriction) Log.e(LOG_TAG, "$restriction set in place. Cannot install." ) return InstallAborted( ABORT_REASON_POLICY, message = restriction, resultIntent = adminSupportDetailsIntent ) Loading Loading @@ -287,7 +304,7 @@ class InstallRepository(private val context: Context) { stagedSessionId = packageInstaller.createSession(params) } } catch (e: Exception) { Log.w(LOG_TAG, "Failed to create a staging session", e) Log.e(LOG_TAG, "Failed to create a staging session", e) _stagingResult.value = InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading @@ -308,6 +325,7 @@ class InstallRepository(private val context: Context) { _stagingResult.value = InstallReady() } else { cleanupStagingSession() Log.e(LOG_TAG, "Could not stage APK.") _stagingResult.value = InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading @@ -318,6 +336,7 @@ class InstallRepository(private val context: Context) { } } } else { Log.e(LOG_TAG, "Invalid URI: ${if (uri == null) "null" else uri.scheme}") _stagingResult.value = InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading Loading @@ -403,8 +422,8 @@ class InstallRepository(private val context: Context) { */ fun requestUserConfirmation(): InstallStage { return if (isTrustedSource) { if (localLOGV) { Log.i(LOG_TAG, "install allowed") if (localLogv) { Log.i(LOG_TAG, "Install allowed") } // Returns InstallUserActionRequired stage if install details could be successfully // computed, else it returns InstallAborted. Loading @@ -428,7 +447,7 @@ class InstallRepository(private val context: Context) { val info = packageInstaller.getSessionInfo(sessionId) val resolvedPath = info?.resolvedBaseApkPath if (info == null || !info.isSealed || resolvedPath == null) { Log.w(LOG_TAG, "Session $sessionId in funky state; ignoring") Log.e(LOG_TAG, "Session $sessionId in funky state; ignoring") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } packageSource = Uri.fromFile(File(resolvedPath)) Loading @@ -440,7 +459,7 @@ class InstallRepository(private val context: Context) { } else if (PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL == intent.action) { val info = packageInstaller.getSessionInfo(sessionId) if (info == null || !info.isPreApprovalRequested) { Log.w(LOG_TAG, "Session $sessionId in funky state; ignoring") Log.e(LOG_TAG, "Session $sessionId in funky state; ignoring") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } packageSource = info Loading @@ -465,7 +484,7 @@ class InstallRepository(private val context: Context) { // if there's nothing to do, quietly slip into the ether if (packageSource == null) { Log.w(LOG_TAG, "Unspecified source") Log.e(LOG_TAG, "Unspecified source") return InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading Loading @@ -509,7 +528,7 @@ class InstallRepository(private val context: Context) { if (scheme == null) { return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "processPackageUri(): uri = $packageUri, scheme = $scheme") } when (scheme) { Loading @@ -528,7 +547,7 @@ class InstallRepository(private val context: Context) { } } if (newPackageInfo == null) { Log.w( Log.e( LOG_TAG, "Requested package " + packageUri.schemeSpecificPart + " not available. Discontinuing installation" ) Loading @@ -542,7 +561,7 @@ class InstallRepository(private val context: Context) { ) } appSnippet = getAppSnippet(context, newPackageInfo!!) if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Created snippet for " + appSnippet.label) } } Loading @@ -569,7 +588,7 @@ class InstallRepository(private val context: Context) { activityResultCode = Activity.RESULT_FIRST_USER ) } if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Creating snippet for local file $sourceFile") } appSnippet = getAppSnippet(context, newPackageInfo!!, sourceFile!!) Loading @@ -590,9 +609,7 @@ class InstallRepository(private val context: Context) { * Use the SessionInfo and set up the installer for pre-commit install session. * * @param sessionInfo The SessionInfo to compose * @return * * [InstallUserActionRequired] if source could be processed * * [InstallAborted] if source is invalid or there was an error is processing a source * @return [InstallUserActionRequired] */ private fun processSessionInfo(sessionInfo: SessionInfo, userActionReason: Int): InstallStage { newPackageInfo = generateStubPackageInfo(sessionInfo.getAppPackageName()) Loading Loading @@ -718,7 +735,7 @@ class InstallRepository(private val context: Context) { appOpStr!!, requestInfo.originatingUid, requestInfo.callingPackage, requestInfo.attributionTag, "Started package installation activity" ) if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "handleUnknownSources(): appMode=$appOpMode") } Loading Loading @@ -764,6 +781,9 @@ class InstallRepository(private val context: Context) { fun initiateInstall() { if (sessionId > 0) { packageInstaller.setPermissionsResult(sessionId, true) if (localLogv) { Log.i(LOG_TAG, "Install permission granted for session $sessionId") } _installResult.value = InstallAborted( ABORT_REASON_DONE, activityResultCode = Activity.RESULT_OK ) Loading Loading @@ -824,8 +844,13 @@ class InstallRepository(private val context: Context) { private fun setStageBasedOnResult( statusCode: Int, legacyStatus: Int, message: String? message: String?, ) { if (localLogv) { Log.i(LOG_TAG, "Status code: $statusCode\n" + "legacy status: $legacyStatus\n" + "message: $message") } if (statusCode == PackageInstaller.STATUS_SUCCESS) { val shouldReturnResult = intent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false) val resultIntent = if (shouldReturnResult) { Loading packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt +8 −3 Original line number Diff line number Diff line Loading @@ -36,7 +36,8 @@ import java.io.File object PackageUtil { private val LOG_TAG = InstallRepository::class.java.simpleName private const val DOWNLOADS_AUTHORITY = "downloads" private const val SPLIT_BASE_APK_END_WITH = "base.apk" private const val SPLIT_BASE_APK_SUFFIX = "base.apk" const val localLogv = false /** * Determines if the UID belongs to the system downloads provider and returns the Loading Loading @@ -394,7 +395,7 @@ object PackageUtil { @JvmStatic fun getPackageInfo(context: Context, sourceFile: File, flags: Int): PackageInfo? { var filePath = sourceFile.absolutePath if (filePath.endsWith(SPLIT_BASE_APK_END_WITH)) { if (filePath.endsWith(SPLIT_BASE_APK_SUFFIX)) { val dir = sourceFile.parentFile if ((dir?.listFiles()?.size ?: 0) > 1) { // split apks, use file directory to get archive info Loading Loading @@ -436,5 +437,9 @@ object PackageUtil { * The class to hold an incoming package's icon and label. * See [getAppSnippet] */ data class AppSnippet(var label: CharSequence?, var icon: Drawable?) data class AppSnippet(var label: CharSequence?, var icon: Drawable?) { override fun toString(): String { return "AppSnippet[label = ${label}, hasIcon = ${icon != null}]" } } } packages/PackageInstaller/src/com/android/packageinstaller/v2/model/UninstallRepository.kt +7 −4 Original line number Diff line number Diff line Loading @@ -226,18 +226,19 @@ class UninstallRepository(private val context: Context) { userName ) if (userManager!!.isSameProfileGroup(myUserHandle, uninstalledUser!!)) { if (customUserManager!!.isManagedProfile()) { if (customUserManager.isManagedProfile) { messageString = context.getString( R.string.uninstall_application_text_current_user_work_profile, userName ) } else if (customUserManager!!.isCloneProfile()){ } else if (customUserManager.isCloneProfile){ isClonedApp = true messageString = context.getString( R.string.uninstall_application_text_current_user_clone_profile ) } else if (Flags.allowPrivateProfile() && android.multiuser.Flags.enablePrivateSpaceFeatures() && customUserManager!!.isPrivateProfile()) { && customUserManager.isPrivateProfile ) { // TODO(b/324244123): Get these Strings from a User Property API. messageString = context.getString( R.string.uninstall_application_text_current_user_private_profile Loading Loading @@ -401,6 +402,7 @@ class UninstallRepository(private val context: Context) { uninstallData.putBoolean(Intent.EXTRA_UNINSTALL_ALL_USERS, uninstallFromAllUsers) uninstallData.putCharSequence(EXTRA_APP_LABEL, targetAppLabel) uninstallData.putBoolean(EXTRA_IS_CLONE_APP, isClonedApp) uninstallData.putInt(EXTRA_TARGET_USER_ID, uninstalledUser!!.identifier) Log.i(LOG_TAG, "Uninstalling extras = $uninstallData") // Get a PendingIntent for result broadcast and issue an uninstall request Loading Loading @@ -730,7 +732,7 @@ class UninstallRepository(private val context: Context) { } } fun cancelInstall() { fun cancelUninstall() { if (callback != null) { callback!!.onUninstallComplete( targetPackageName!!, Loading @@ -749,6 +751,7 @@ class UninstallRepository(private val context: Context) { private const val EXTRA_IS_CLONE_APP = "com.android.packageinstaller.extra.IS_CLONE_APP" private const val EXTRA_PACKAGE_NAME = "com.android.packageinstaller.extra.EXTRA_PACKAGE_NAME" private const val EXTRA_TARGET_USER_ID = "EXTRA_TARGET_USER_ID" } class CallerInfo(val activityName: String?, val uid: Int) Loading packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt +19 −5 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ 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 import com.android.packageinstaller.v2.model.PackageUtil.localLogv import com.android.packageinstaller.v2.ui.fragments.AnonymousSourceFragment import com.android.packageinstaller.v2.ui.fragments.ExternalSourcesBlockedFragment import com.android.packageinstaller.v2.ui.fragments.InstallConfirmationFragment Loading @@ -66,8 +67,6 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { private const val TAG_DIALOG = "dialog" } private val localLOGV = false /** * A collection of unknown sources listeners that are actively listening for app ops mode * changes Loading Loading @@ -199,14 +198,14 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { // admin enforcing the restriction for the affected user. If not enforced by the admin, // show the system dialog. if (adminSupportIntent != null) { if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Restriction set by admin, starting $adminSupportIntent") } startActivity(adminSupportIntent) // Finish the package installer app since the next dialog will not be shown by this app shouldFinish = true } else { if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Restriction set by system: $restriction") } val blockedByPolicyDialog = createDevicePolicyRestrictionDialog(restriction) Loading @@ -225,7 +224,7 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { * @return The dialog */ private fun createDevicePolicyRestrictionDialog(restriction: String?): DialogFragment? { if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "createDialog($restriction)") } return when (restriction) { Loading Loading @@ -259,6 +258,9 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun onPositiveResponse(reasonCode: Int) { if (localLogv) { Log.d(LOG_TAG, "Positive button clicked. ReasonCode: $reasonCode") } when (reasonCode) { InstallUserActionRequired.USER_ACTION_REASON_ANONYMOUS_SOURCE -> installViewModel!!.forcedSkipSourceCheck() Loading @@ -269,6 +271,9 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun onNegativeResponse(stageCode: Int) { if (localLogv) { Log.d(LOG_TAG, "Negative button clicked. StageCode: $stageCode") } if (stageCode == InstallStage.STAGE_USER_ACTION_REQUIRED) { installViewModel!!.cleanupInstall() } Loading @@ -276,10 +281,16 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun onNegativeResponse(resultCode: Int, data: Intent?) { if (localLogv) { Log.d(LOG_TAG, "Negative button clicked. resultCode: $resultCode; Intent: $data") } setResult(resultCode, data, true) } override fun sendUnknownAppsIntent(sourcePackageName: String) { if (localLogv) { Log.d(LOG_TAG, "Launching unknown-apps settings intent for $sourcePackageName") } val settingsIntent = Intent() settingsIntent.setAction(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) val packageUri = Uri.parse("package:$sourcePackageName") Loading @@ -299,6 +310,9 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun openInstalledApp(intent: Intent?) { if (localLogv) { Log.d(LOG_TAG, "Opening $intent") } setResult(Activity.RESULT_OK, intent, true) if (intent != null && intent.hasCategory(Intent.CATEGORY_LAUNCHER)) { startActivity(intent) Loading packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt +8 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentManager import androidx.lifecycle.ViewModelProvider import com.android.packageinstaller.v2.model.PackageUtil.localLogv import com.android.packageinstaller.v2.model.UninstallAborted import com.android.packageinstaller.v2.model.UninstallFailed import com.android.packageinstaller.v2.model.UninstallRepository Loading Loading @@ -159,11 +160,17 @@ class UninstallLaunch : FragmentActivity(), UninstallActionListener { } override fun onPositiveResponse(keepData: Boolean) { if (localLogv) { Log.d(LOG_TAG, "Staring uninstall") } uninstallViewModel!!.initiateUninstall(keepData) } override fun onNegativeResponse() { uninstallViewModel!!.cancelInstall() if (localLogv) { Log.d(LOG_TAG, "Cancelling uninstall") } uninstallViewModel!!.cancelUninstall() setResult(Activity.RESULT_FIRST_USER, null, true) } } Loading
packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallRepository.kt +41 −16 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.packageinstaller.v2.model.PackageUtil.getPackageNameForUid import com.android.packageinstaller.v2.model.PackageUtil.isCallerSessionOwner import com.android.packageinstaller.v2.model.PackageUtil.isInstallPermissionGrantedOrRequested import com.android.packageinstaller.v2.model.PackageUtil.isPermissionGranted import com.android.packageinstaller.v2.model.PackageUtil.localLogv import java.io.File import java.io.IOException import kotlinx.coroutines.DelicateCoroutinesApi Loading @@ -75,7 +76,6 @@ class InstallRepository(private val context: Context) { private val devicePolicyManager: DevicePolicyManager? = context.getSystemService(DevicePolicyManager::class.java) private val appOpsManager: AppOpsManager? = context.getSystemService(AppOpsManager::class.java) private val localLOGV = false private var isSessionInstall = false private var isTrustedSource = false private val _stagingResult = MutableLiveData<InstallStage>() Loading Loading @@ -155,8 +155,18 @@ class InstallRepository(private val context: Context) { originatingUid, callingAttributionTag ) if(localLogv) { Log.i(LOG_TAG, "Intent: $intent\n" + "sessionId: $sessionId\n" + "staged sessionId: $stagedSessionId\n" + "calling package: $callingPackage\n" + "callingUid: $callingUid\n" + "originatingUid: $originatingUid") } if (callingUid == Process.INVALID_UID && sourceInfo == null) { // Caller's identity could not be determined. Abort the install Log.e(LOG_TAG, "Cannot determine caller since UID is invalid and sourceInfo is null") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } Loading @@ -165,6 +175,9 @@ class InstallRepository(private val context: Context) { || (stagedSessionId != SessionInfo.INVALID_ID && !isCallerSessionOwner(packageInstaller, Process.myUid(), stagedSessionId)) ) { Log.e(LOG_TAG, "UID is not the owner of the session:\n" + "CallingUid: $originatingUid | SessionId: $sessionId\n" + "My UID: ${Process.myUid()} | StagedSessionId: $stagedSessionId") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } Loading @@ -173,6 +186,9 @@ class InstallRepository(private val context: Context) { context, callingUid, originatingUid, isTrustedSource ) ) { Log.e(LOG_TAG, "UID $originatingUid needs to declare " + Manifest.permission.REQUEST_INSTALL_PACKAGES ) return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } Loading @@ -180,6 +196,7 @@ class InstallRepository(private val context: Context) { if (restriction != null) { val adminSupportDetailsIntent = devicePolicyManager!!.createAdminSupportIntent(restriction) Log.e(LOG_TAG, "$restriction set in place. Cannot install." ) return InstallAborted( ABORT_REASON_POLICY, message = restriction, resultIntent = adminSupportDetailsIntent ) Loading Loading @@ -287,7 +304,7 @@ class InstallRepository(private val context: Context) { stagedSessionId = packageInstaller.createSession(params) } } catch (e: Exception) { Log.w(LOG_TAG, "Failed to create a staging session", e) Log.e(LOG_TAG, "Failed to create a staging session", e) _stagingResult.value = InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading @@ -308,6 +325,7 @@ class InstallRepository(private val context: Context) { _stagingResult.value = InstallReady() } else { cleanupStagingSession() Log.e(LOG_TAG, "Could not stage APK.") _stagingResult.value = InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading @@ -318,6 +336,7 @@ class InstallRepository(private val context: Context) { } } } else { Log.e(LOG_TAG, "Invalid URI: ${if (uri == null) "null" else uri.scheme}") _stagingResult.value = InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading Loading @@ -403,8 +422,8 @@ class InstallRepository(private val context: Context) { */ fun requestUserConfirmation(): InstallStage { return if (isTrustedSource) { if (localLOGV) { Log.i(LOG_TAG, "install allowed") if (localLogv) { Log.i(LOG_TAG, "Install allowed") } // Returns InstallUserActionRequired stage if install details could be successfully // computed, else it returns InstallAborted. Loading @@ -428,7 +447,7 @@ class InstallRepository(private val context: Context) { val info = packageInstaller.getSessionInfo(sessionId) val resolvedPath = info?.resolvedBaseApkPath if (info == null || !info.isSealed || resolvedPath == null) { Log.w(LOG_TAG, "Session $sessionId in funky state; ignoring") Log.e(LOG_TAG, "Session $sessionId in funky state; ignoring") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } packageSource = Uri.fromFile(File(resolvedPath)) Loading @@ -440,7 +459,7 @@ class InstallRepository(private val context: Context) { } else if (PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL == intent.action) { val info = packageInstaller.getSessionInfo(sessionId) if (info == null || !info.isPreApprovalRequested) { Log.w(LOG_TAG, "Session $sessionId in funky state; ignoring") Log.e(LOG_TAG, "Session $sessionId in funky state; ignoring") return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } packageSource = info Loading @@ -465,7 +484,7 @@ class InstallRepository(private val context: Context) { // if there's nothing to do, quietly slip into the ether if (packageSource == null) { Log.w(LOG_TAG, "Unspecified source") Log.e(LOG_TAG, "Unspecified source") return InstallAborted( ABORT_REASON_INTERNAL_ERROR, resultIntent = Intent().putExtra( Loading Loading @@ -509,7 +528,7 @@ class InstallRepository(private val context: Context) { if (scheme == null) { return InstallAborted(ABORT_REASON_INTERNAL_ERROR) } if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "processPackageUri(): uri = $packageUri, scheme = $scheme") } when (scheme) { Loading @@ -528,7 +547,7 @@ class InstallRepository(private val context: Context) { } } if (newPackageInfo == null) { Log.w( Log.e( LOG_TAG, "Requested package " + packageUri.schemeSpecificPart + " not available. Discontinuing installation" ) Loading @@ -542,7 +561,7 @@ class InstallRepository(private val context: Context) { ) } appSnippet = getAppSnippet(context, newPackageInfo!!) if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Created snippet for " + appSnippet.label) } } Loading @@ -569,7 +588,7 @@ class InstallRepository(private val context: Context) { activityResultCode = Activity.RESULT_FIRST_USER ) } if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Creating snippet for local file $sourceFile") } appSnippet = getAppSnippet(context, newPackageInfo!!, sourceFile!!) Loading @@ -590,9 +609,7 @@ class InstallRepository(private val context: Context) { * Use the SessionInfo and set up the installer for pre-commit install session. * * @param sessionInfo The SessionInfo to compose * @return * * [InstallUserActionRequired] if source could be processed * * [InstallAborted] if source is invalid or there was an error is processing a source * @return [InstallUserActionRequired] */ private fun processSessionInfo(sessionInfo: SessionInfo, userActionReason: Int): InstallStage { newPackageInfo = generateStubPackageInfo(sessionInfo.getAppPackageName()) Loading Loading @@ -718,7 +735,7 @@ class InstallRepository(private val context: Context) { appOpStr!!, requestInfo.originatingUid, requestInfo.callingPackage, requestInfo.attributionTag, "Started package installation activity" ) if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "handleUnknownSources(): appMode=$appOpMode") } Loading Loading @@ -764,6 +781,9 @@ class InstallRepository(private val context: Context) { fun initiateInstall() { if (sessionId > 0) { packageInstaller.setPermissionsResult(sessionId, true) if (localLogv) { Log.i(LOG_TAG, "Install permission granted for session $sessionId") } _installResult.value = InstallAborted( ABORT_REASON_DONE, activityResultCode = Activity.RESULT_OK ) Loading Loading @@ -824,8 +844,13 @@ class InstallRepository(private val context: Context) { private fun setStageBasedOnResult( statusCode: Int, legacyStatus: Int, message: String? message: String?, ) { if (localLogv) { Log.i(LOG_TAG, "Status code: $statusCode\n" + "legacy status: $legacyStatus\n" + "message: $message") } if (statusCode == PackageInstaller.STATUS_SUCCESS) { val shouldReturnResult = intent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false) val resultIntent = if (shouldReturnResult) { Loading
packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt +8 −3 Original line number Diff line number Diff line Loading @@ -36,7 +36,8 @@ import java.io.File object PackageUtil { private val LOG_TAG = InstallRepository::class.java.simpleName private const val DOWNLOADS_AUTHORITY = "downloads" private const val SPLIT_BASE_APK_END_WITH = "base.apk" private const val SPLIT_BASE_APK_SUFFIX = "base.apk" const val localLogv = false /** * Determines if the UID belongs to the system downloads provider and returns the Loading Loading @@ -394,7 +395,7 @@ object PackageUtil { @JvmStatic fun getPackageInfo(context: Context, sourceFile: File, flags: Int): PackageInfo? { var filePath = sourceFile.absolutePath if (filePath.endsWith(SPLIT_BASE_APK_END_WITH)) { if (filePath.endsWith(SPLIT_BASE_APK_SUFFIX)) { val dir = sourceFile.parentFile if ((dir?.listFiles()?.size ?: 0) > 1) { // split apks, use file directory to get archive info Loading Loading @@ -436,5 +437,9 @@ object PackageUtil { * The class to hold an incoming package's icon and label. * See [getAppSnippet] */ data class AppSnippet(var label: CharSequence?, var icon: Drawable?) data class AppSnippet(var label: CharSequence?, var icon: Drawable?) { override fun toString(): String { return "AppSnippet[label = ${label}, hasIcon = ${icon != null}]" } } }
packages/PackageInstaller/src/com/android/packageinstaller/v2/model/UninstallRepository.kt +7 −4 Original line number Diff line number Diff line Loading @@ -226,18 +226,19 @@ class UninstallRepository(private val context: Context) { userName ) if (userManager!!.isSameProfileGroup(myUserHandle, uninstalledUser!!)) { if (customUserManager!!.isManagedProfile()) { if (customUserManager.isManagedProfile) { messageString = context.getString( R.string.uninstall_application_text_current_user_work_profile, userName ) } else if (customUserManager!!.isCloneProfile()){ } else if (customUserManager.isCloneProfile){ isClonedApp = true messageString = context.getString( R.string.uninstall_application_text_current_user_clone_profile ) } else if (Flags.allowPrivateProfile() && android.multiuser.Flags.enablePrivateSpaceFeatures() && customUserManager!!.isPrivateProfile()) { && customUserManager.isPrivateProfile ) { // TODO(b/324244123): Get these Strings from a User Property API. messageString = context.getString( R.string.uninstall_application_text_current_user_private_profile Loading Loading @@ -401,6 +402,7 @@ class UninstallRepository(private val context: Context) { uninstallData.putBoolean(Intent.EXTRA_UNINSTALL_ALL_USERS, uninstallFromAllUsers) uninstallData.putCharSequence(EXTRA_APP_LABEL, targetAppLabel) uninstallData.putBoolean(EXTRA_IS_CLONE_APP, isClonedApp) uninstallData.putInt(EXTRA_TARGET_USER_ID, uninstalledUser!!.identifier) Log.i(LOG_TAG, "Uninstalling extras = $uninstallData") // Get a PendingIntent for result broadcast and issue an uninstall request Loading Loading @@ -730,7 +732,7 @@ class UninstallRepository(private val context: Context) { } } fun cancelInstall() { fun cancelUninstall() { if (callback != null) { callback!!.onUninstallComplete( targetPackageName!!, Loading @@ -749,6 +751,7 @@ class UninstallRepository(private val context: Context) { private const val EXTRA_IS_CLONE_APP = "com.android.packageinstaller.extra.IS_CLONE_APP" private const val EXTRA_PACKAGE_NAME = "com.android.packageinstaller.extra.EXTRA_PACKAGE_NAME" private const val EXTRA_TARGET_USER_ID = "EXTRA_TARGET_USER_ID" } class CallerInfo(val activityName: String?, val uid: Int) Loading
packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt +19 −5 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ 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 import com.android.packageinstaller.v2.model.PackageUtil.localLogv import com.android.packageinstaller.v2.ui.fragments.AnonymousSourceFragment import com.android.packageinstaller.v2.ui.fragments.ExternalSourcesBlockedFragment import com.android.packageinstaller.v2.ui.fragments.InstallConfirmationFragment Loading @@ -66,8 +67,6 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { private const val TAG_DIALOG = "dialog" } private val localLOGV = false /** * A collection of unknown sources listeners that are actively listening for app ops mode * changes Loading Loading @@ -199,14 +198,14 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { // admin enforcing the restriction for the affected user. If not enforced by the admin, // show the system dialog. if (adminSupportIntent != null) { if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Restriction set by admin, starting $adminSupportIntent") } startActivity(adminSupportIntent) // Finish the package installer app since the next dialog will not be shown by this app shouldFinish = true } else { if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "Restriction set by system: $restriction") } val blockedByPolicyDialog = createDevicePolicyRestrictionDialog(restriction) Loading @@ -225,7 +224,7 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { * @return The dialog */ private fun createDevicePolicyRestrictionDialog(restriction: String?): DialogFragment? { if (localLOGV) { if (localLogv) { Log.i(LOG_TAG, "createDialog($restriction)") } return when (restriction) { Loading Loading @@ -259,6 +258,9 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun onPositiveResponse(reasonCode: Int) { if (localLogv) { Log.d(LOG_TAG, "Positive button clicked. ReasonCode: $reasonCode") } when (reasonCode) { InstallUserActionRequired.USER_ACTION_REASON_ANONYMOUS_SOURCE -> installViewModel!!.forcedSkipSourceCheck() Loading @@ -269,6 +271,9 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun onNegativeResponse(stageCode: Int) { if (localLogv) { Log.d(LOG_TAG, "Negative button clicked. StageCode: $stageCode") } if (stageCode == InstallStage.STAGE_USER_ACTION_REQUIRED) { installViewModel!!.cleanupInstall() } Loading @@ -276,10 +281,16 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun onNegativeResponse(resultCode: Int, data: Intent?) { if (localLogv) { Log.d(LOG_TAG, "Negative button clicked. resultCode: $resultCode; Intent: $data") } setResult(resultCode, data, true) } override fun sendUnknownAppsIntent(sourcePackageName: String) { if (localLogv) { Log.d(LOG_TAG, "Launching unknown-apps settings intent for $sourcePackageName") } val settingsIntent = Intent() settingsIntent.setAction(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) val packageUri = Uri.parse("package:$sourcePackageName") Loading @@ -299,6 +310,9 @@ class InstallLaunch : FragmentActivity(), InstallActionListener { } override fun openInstalledApp(intent: Intent?) { if (localLogv) { Log.d(LOG_TAG, "Opening $intent") } setResult(Activity.RESULT_OK, intent, true) if (intent != null && intent.hasCategory(Intent.CATEGORY_LAUNCHER)) { startActivity(intent) Loading
packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt +8 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentManager import androidx.lifecycle.ViewModelProvider import com.android.packageinstaller.v2.model.PackageUtil.localLogv import com.android.packageinstaller.v2.model.UninstallAborted import com.android.packageinstaller.v2.model.UninstallFailed import com.android.packageinstaller.v2.model.UninstallRepository Loading Loading @@ -159,11 +160,17 @@ class UninstallLaunch : FragmentActivity(), UninstallActionListener { } override fun onPositiveResponse(keepData: Boolean) { if (localLogv) { Log.d(LOG_TAG, "Staring uninstall") } uninstallViewModel!!.initiateUninstall(keepData) } override fun onNegativeResponse() { uninstallViewModel!!.cancelInstall() if (localLogv) { Log.d(LOG_TAG, "Cancelling uninstall") } uninstallViewModel!!.cancelUninstall() setResult(Activity.RESULT_FIRST_USER, null, true) } }