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

Commit 926fd3ca authored by Patrick Baumann's avatar Patrick Baumann
Browse files

Skip back for unknown sources

This change uses an appops observer to automatically relaunch the
package installer acativity to the front of the task when the user
chooses to allow installs from unknown sources.

Bug: 183960866
Test: atest CtsPackageInstallTestCases
Change-Id: I8fccb0b296752ba30e1cc19b719d964df893079a
parent dabc72e5
Loading
Loading
Loading
Loading
+63 −6
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
*/
package com.android.packageinstaller;

import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY;
import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;

import android.Manifest;
@@ -50,6 +52,8 @@ import android.widget.Button;
import com.android.internal.app.AlertActivity;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * This activity is launched when a new application is installed via side loading
@@ -92,6 +96,12 @@ public class PackageInstallerActivity extends AlertActivity {
    private String mCallingAttributionTag;
    ApplicationInfo mSourceInfo;

    /**
     * A collection of unknown sources listeners that are actively listening for app ops mode
     * changes
     */
    private List<UnknownSourcesListener> mActiveUnknownSourcesListeners = new ArrayList<>(1);

    // ApplicationInfo object primarily used for already existing applications
    private ApplicationInfo mAppInfo = null;

@@ -381,6 +391,14 @@ public class PackageInstallerActivity extends AlertActivity {
        outState.putBoolean(ALLOW_UNKNOWN_SOURCES_KEY, mAllowUnknownSources);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        while (!mActiveUnknownSourcesListeners.isEmpty()) {
            unregister(mActiveUnknownSourcesListeners.get(0));
        }
    }

    private void bindUi() {
        mAlert.setIcon(mAppSnippet.icon);
        mAlert.setTitle(mAppSnippet.label);
@@ -707,24 +725,61 @@ public class PackageInstallerActivity extends AlertActivity {
        }
    }

    private class UnknownSourcesListener implements AppOpsManager.OnOpChangedListener {

        @Override
        public void onOpChanged(String op, String packageName) {
            if (!mOriginatingPackage.equals(packageName)) {
                return;
            }
            unregister(this);
            mActiveUnknownSourcesListeners.remove(this);
            if (isDestroyed()) {
                return;
            }
            getMainThreadHandler().postDelayed(() -> {
                if (!isDestroyed()) {
                    startActivity(getIntent().addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT));
                }
            }, 500);

        }

    }

    private void register(UnknownSourcesListener listener) {
        mAppOpsManager.startWatchingMode(
                AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES, mOriginatingPackage,
                listener);
        mActiveUnknownSourcesListeners.add(listener);
    }

    private void unregister(UnknownSourcesListener listener) {
        mAppOpsManager.stopWatchingMode(listener);
        mActiveUnknownSourcesListeners.remove(listener);
    }

    /**
     * An error dialog shown when external sources are not allowed
     */
    public static class ExternalSourcesBlockedDialog extends AppErrorDialog {
        static AppErrorDialog newInstance(@NonNull String originationPkg) {
            ExternalSourcesBlockedDialog dialog = new ExternalSourcesBlockedDialog();
            ExternalSourcesBlockedDialog dialog =
                    new ExternalSourcesBlockedDialog();
            dialog.setArgument(originationPkg);
            return dialog;
        }

        @Override
        protected Dialog createDialog(@NonNull CharSequence argument) {

            final PackageInstallerActivity activity = (PackageInstallerActivity)getActivity();
            try {
                PackageManager pm = getActivity().getPackageManager();
                PackageManager pm = activity.getPackageManager();

                ApplicationInfo sourceInfo = pm.getApplicationInfo(argument.toString(), 0);

                return new AlertDialog.Builder(getActivity())
                return new AlertDialog.Builder(activity)
                        .setTitle(pm.getApplicationLabel(sourceInfo))
                        .setIcon(pm.getApplicationIcon(sourceInfo))
                        .setMessage(R.string.untrusted_external_source_warning)
@@ -735,8 +790,10 @@ public class PackageInstallerActivity extends AlertActivity {
                                            Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                                    final Uri packageUri = Uri.parse("package:" + argument);
                                    settingsIntent.setData(packageUri);
                                    settingsIntent.setFlags(FLAG_ACTIVITY_NO_HISTORY);
                                    try {
                                        getActivity().startActivityForResult(settingsIntent,
                                        activity.register(activity.new UnknownSourcesListener());
                                        activity.startActivityForResult(settingsIntent,
                                                REQUEST_TRUST_EXTERNAL_SOURCE);
                                    } catch (ActivityNotFoundException exc) {
                                        Log.e(TAG, "Settings activity not found for action: "
@@ -744,11 +801,11 @@ public class PackageInstallerActivity extends AlertActivity {
                                    }
                                })
                        .setNegativeButton(R.string.cancel,
                                (dialog, which) -> getActivity().finish())
                                (dialog, which) -> activity.finish())
                        .create();
            } catch (NameNotFoundException e) {
                Log.e(TAG, "Did not find app info for " + argument);
                getActivity().finish();
                activity.finish();
                return null;
            }
        }