From 926fd3ca8b94babf40a6663d1732f5962fc4c7d0 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Tue, 6 Apr 2021 10:11:32 -0700 Subject: [PATCH] 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 --- .../PackageInstallerActivity.java | 69 +++++++++++++++++-- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java index 4578597a5a9d9..95f180a9ba329 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -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 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; } }