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

Commit aebbd5b7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Hide spannable link if it's not actionable" into pi-dev

parents 9492aa54 1ee2a88f
Loading
Loading
Loading
Loading
+5 −18
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -99,8 +98,6 @@ public class FingerprintSettings extends SubSettings {
    public static final String ANNOTATION_URL = "url";
    public static final String ANNOTATION_ADMIN_DETAILS = "admin_details";

    public static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings";

    @Override
    public Intent getIntent() {
        Intent modIntent = new Intent(super.getIntent());
@@ -158,20 +155,6 @@ public class FingerprintSettings extends SubSettings {
        private FingerprintRemoveSidecar mRemovalSidecar;
        private HashMap<Integer, String> mFingerprintsRenaming;

        final AnnotationSpan.LinkInfo mUrlLinkInfo = new AnnotationSpan.LinkInfo(
                ANNOTATION_URL, (view) -> {
            final Context context = view.getContext();
            Intent intent = HelpUtils.getHelpIntent(context, getString(getHelpResource()),
                    context.getClass().getName());
            if (intent != null) {
                try {
                    view.startActivityForResult(intent, 0);
                } catch (ActivityNotFoundException e) {
                    Log.w(TAG, "Activity was not found for intent, " + intent.toString());
                }
            }
        });

        FingerprintAuthenticateSidecar.Listener mAuthenticateListener =
            new FingerprintAuthenticateSidecar.Listener() {
                @Override
@@ -360,11 +343,15 @@ public class FingerprintSettings extends SubSettings {
                    ANNOTATION_ADMIN_DETAILS, (view) -> {
                RestrictedLockUtils.sendShowAdminSupportDetailsIntent(activity, admin);
            });
            final Intent helpIntent = HelpUtils.getHelpIntent(
                    activity, getString(getHelpResource()), activity.getClass().getName());
            final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
                    activity, ANNOTATION_URL, helpIntent);
            pref.setTitle(AnnotationSpan.linkify(getText(admin != null
                            ? R.string
                            .security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled
                            : R.string.security_settings_fingerprint_enroll_disclaimer),
                    mUrlLinkInfo, adminLinkInfo));
                    linkInfo, adminLinkInfo));
        }

        protected void removeFingerprintPreference(int fingerprintId) {
+10 −20
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
@@ -33,7 +32,6 @@ import android.support.annotation.VisibleForTesting;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
@@ -58,7 +56,7 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp

    public static final String ANNOTATION_URL = "url";

    private static final String TAG = "PrivateDnsModeDialogFragment";
    private static final String TAG = "PrivateDnsModeDialog";
    // DNS_MODE -> RadioButton id
    private static final Map<String, Integer> PRIVATE_DNS_MAP;

@@ -83,21 +81,6 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp
    @VisibleForTesting
    String mMode;

    private final AnnotationSpan.LinkInfo mUrlLinkInfo = new AnnotationSpan.LinkInfo(
            ANNOTATION_URL, (widget) -> {
        final Context context = widget.getContext();
        final Intent intent = HelpUtils.getHelpIntent(context,
                getString(R.string.help_uri_private_dns),
                context.getClass().getName());
        if (intent != null) {
            try {
                widget.startActivityForResult(intent, 0);
            } catch (ActivityNotFoundException e) {
                Log.w(TAG, "Activity was not found for intent, " + intent.toString());
            }
        }
    });

    public static void show(FragmentManager fragmentManager) {
        if (fragmentManager.findFragmentByTag(TAG) == null) {
            final PrivateDnsModeDialogFragment fragment = new PrivateDnsModeDialogFragment();
@@ -139,8 +122,15 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp

        final TextView helpTextView = view.findViewById(R.id.private_dns_help_info);
        helpTextView.setMovementMethod(LinkMovementMethod.getInstance());
        final Intent helpIntent = HelpUtils.getHelpIntent(context,
                context.getString(R.string.help_uri_private_dns),
                context.getClass().getName());
        final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(context,
                ANNOTATION_URL, helpIntent);
        if (linkInfo.isActionable()) {
            helpTextView.setText(AnnotationSpan.linkify(
                context.getText(R.string.private_dns_help_message), mUrlLinkInfo));
                    context.getText(R.string.private_dns_help_message), linkInfo));
        }

        return view;
    }
+39 −6
Original line number Diff line number Diff line
@@ -16,11 +16,15 @@

package com.android.settings.utils;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.text.Annotation;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.style.URLSpan;
import android.util.Log;
import android.view.View;

/**
@@ -28,6 +32,7 @@ import android.view.View;
 * annotation.
 */
public class AnnotationSpan extends URLSpan {

    private final View.OnClickListener mClickListener;

    private AnnotationSpan(View.OnClickListener lsn) {
@@ -58,8 +63,8 @@ public class AnnotationSpan extends URLSpan {
            int end = msg.getSpanEnd(annotation);
            AnnotationSpan link = null;
            for (LinkInfo linkInfo : linkInfos) {
                if (linkInfo.annotation.equals(key)) {
                    link = new AnnotationSpan(linkInfo.listener);
                if (linkInfo.mAnnotation.equals(key)) {
                    link = new AnnotationSpan(linkInfo.mListener);
                    break;
                }
            }
@@ -74,12 +79,40 @@ public class AnnotationSpan extends URLSpan {
     * Data class to store the annotation and the click action
     */
    public static class LinkInfo {
        public final String annotation;
        public final View.OnClickListener listener;
        private static final String TAG = "AnnotationSpan.LinkInfo";
        private final String mAnnotation;
        private final Boolean mActionable;
        private final View.OnClickListener mListener;

        public LinkInfo(String annotation, View.OnClickListener listener) {
            this.annotation = annotation;
            this.listener = listener;
            mAnnotation = annotation;
            mListener = listener;
            mActionable = true; // assume actionable
        }

        public LinkInfo(Context context, String annotation, Intent intent) {
            mAnnotation = annotation;
            if (intent != null) {
                mActionable = context.getPackageManager()
                        .resolveActivity(intent, 0 /* flags */) != null;
            } else {
                mActionable = false;
            }
            if (!mActionable) {
                mListener = null;
            } else {
                mListener = view -> {
                    try {
                        view.startActivityForResult(intent, 0);
                    } catch (ActivityNotFoundException e) {
                        Log.w(TAG, "Activity was not found for intent, " + intent);
                    }
                };
            }
        }

        public boolean isActionable() {
            return mActionable;
        }
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -29,14 +29,17 @@ import android.widget.Button;

import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowHelpUtils;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowHelpUtils.class)
public class PrivateDnsModeDialogFragmentTest {

    private static final String HOST_NAME = "192.168.1.1";
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.settings.utils;

import static com.google.common.truth.Truth.assertThat;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;

import com.android.settings.testutils.SettingsRobolectricTestRunner;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;

@RunWith(SettingsRobolectricTestRunner.class)
public class AnnotationSpanTest {

    private Intent mTestIntent;
    private Context mContext;
    private ShadowPackageManager mPackageManager;

    @Before
    public void setUp() {
        mContext = RuntimeEnvironment.application;
        mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
        mTestIntent = new Intent("test_action");
    }

    @Test
    public void newLinkInfo_validIntent_isActionable() {
        mPackageManager.addResolveInfoForIntent(mTestIntent, new ResolveInfo());
        assertThat(new AnnotationSpan.LinkInfo(mContext, "annotation", mTestIntent).isActionable())
                .isTrue();
    }

    @Test
    public void newLinkInfo_invalidIntent_isNotActionable() {
        assertThat(new AnnotationSpan.LinkInfo(mContext, "annotation", mTestIntent).isActionable())
                .isFalse();
    }
}