It first check for cases that can fail fast, then forward to {@link AutofillPickerActivity} + * if necessary. + */ +public class AutofillPickerTrampolineActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // First check if the current user's service already belongs to the app... + final Intent intent = getIntent(); + final String packageName = intent.getData().getSchemeSpecificPart(); + final String currentService = DefaultAutofillPicker.getDefaultKey(this); + if (currentService != null && currentService.startsWith(packageName)) { + // ...and succeed right away if it does. + setResult(RESULT_OK); + finish(); + return; + } + + // Then check if the Autofill is available for the current user... + final AutofillManager afm = getSystemService(AutofillManager.class); + if (afm == null || !afm.hasAutofillFeature() || !afm.isAutofillSupported()) { + // ... and fail right away if it is not. + setResult(RESULT_CANCELED); + finish(); + return; + } + + // Otherwise, go ahead and show the real UI... + final Intent newIntent = new Intent(this, AutofillPickerActivity.class) + .setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) + .setData(intent.getData()); + startActivity(newIntent); + finish(); + } +} diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java index 9ab704ed389..73f4bbe9720 100644 --- a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java +++ b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java @@ -55,8 +55,8 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment if (TextUtils.isEmpty(confirmationMessage)) { super.onRadioButtonClicked(selected); } else if (activity != null) { - final DialogFragment fragment = ConfirmationDialogFragment.newInstance( - this, selectedKey, confirmationMessage); + final DialogFragment fragment = + newConfirmationDialogFragment(selectedKey, confirmationMessage); fragment.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG); } } @@ -74,6 +74,11 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment } } + protected ConfirmationDialogFragment newConfirmationDialogFragment(String selectedKey, + CharSequence confirmationMessage) { + return ConfirmationDialogFragment.newInstance(this, selectedKey, confirmationMessage); + } + protected CharSequence getConfirmationMessage(CandidateInfo info) { return null; } @@ -85,6 +90,12 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment public static final String EXTRA_KEY = "extra_key"; public static final String EXTRA_MESSAGE = "extra_message"; + private final DialogInterface.OnClickListener mCancelListener; + + private ConfirmationDialogFragment(DialogInterface.OnClickListener cancelListener) { + mCancelListener = cancelListener; + } + @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.DEFAULT_APP_PICKER_CONFIRMATION_DIALOG; @@ -92,7 +103,14 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment public static ConfirmationDialogFragment newInstance(DefaultAppPickerFragment parent, String key, CharSequence message) { - final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment(); + return newInstance(parent, key, message, null); + } + + // TODO: add test case for cancelListener + public static ConfirmationDialogFragment newInstance(DefaultAppPickerFragment parent, + String key, CharSequence message, DialogInterface.OnClickListener cancelListener) { + final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment( + cancelListener); final Bundle argument = new Bundle(); argument.putString(EXTRA_KEY, key); argument.putCharSequence(EXTRA_MESSAGE, message); @@ -107,7 +125,7 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) .setMessage(bundle.getCharSequence(EXTRA_MESSAGE)) .setPositiveButton(android.R.string.ok, this) - .setNegativeButton(android.R.string.cancel, null); + .setNegativeButton(android.R.string.cancel, mCancelListener); return builder.create(); } diff --git a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java index 037cddfab67..2e79660446e 100644 --- a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java +++ b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java @@ -18,10 +18,13 @@ package com.android.settings.applications.defaultapps; import android.app.Activity; import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.os.Bundle; import android.provider.Settings; import android.service.autofill.AutofillService; import android.service.autofill.AutofillServiceInfo; @@ -30,6 +33,7 @@ import android.text.TextUtils; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; +import com.android.settings.applications.defaultapps.DefaultAppPickerFragment.ConfirmationDialogFragment; import java.util.ArrayList; import java.util.List; @@ -39,7 +43,35 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment { static final String SETTING = Settings.Secure.AUTOFILL_SERVICE; static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE); - static final String EXTRA_PACKAGE_NAME = "package_name"; + /** + * Extra set when the fragment is implementing ACTION_REQUEST_SET_AUTOFILL_SERVICE. + */ + public static final String EXTRA_PACKAGE_NAME = "package_name"; + + /** + * Set when the fragment is implementing ACTION_REQUEST_SET_AUTOFILL_SERVICE. + */ + public DialogInterface.OnClickListener mCancelListener; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Activity activity = getActivity(); + if (activity != null && activity.getIntent().getStringExtra(EXTRA_PACKAGE_NAME) != null) { + mCancelListener = (d, w) -> { + activity.setResult(Activity.RESULT_CANCELED); + activity.finish(); + }; + } + } + + @Override + protected ConfirmationDialogFragment newConfirmationDialogFragment(String selectedKey, + CharSequence confirmationMessage) { + return ConfirmationDialogFragment.newInstance(this, selectedKey, confirmationMessage, + mCancelListener); + } @Override public int getMetricsCategory() { @@ -63,9 +95,13 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment { return candidates; } + public static String getDefaultKey(Context context) { + return Settings.Secure.getString(context.getContentResolver(), SETTING); + } + @Override protected String getDefaultKey() { - return Settings.Secure.getString(getContext().getContentResolver(), SETTING); + return getDefaultKey(getContext()); } @Override