Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2be3165 authored by Sumedh Sen's avatar Sumedh Sen
Browse files

Check whether content providers can be accessed in Pia V2

A new error dialog is introduced for when a content provider cannot be
accessed due to caller not having visibility of the provider. Also,
handle SecurityException thrown when an unexported content provider is
accessed.

Bug: 182205982
Test: atest CtsContentProviderTestsWithoutVisibility CtsContentProviderTestsWithVisibility
Change-Id: Ic1db1811e92c7b93e64bbdafcd44fe634e5922f5
parent 9aaa9246
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -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
            )
        }
    }

+2 −1
Original line number Diff line number Diff line
@@ -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
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -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.
     */
+16 −4
Original line number Diff line number Diff line
@@ -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 ->
                    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)
+64 −0
Original line number Diff line number Diff line
/*
 * 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());
    }
}