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

Commit 8c427e65 authored by Kanyinsola Fapohunda's avatar Kanyinsola Fapohunda
Browse files

Hide "Send feedback" button if no target exists.

This change hides the "Send feedback" button  when a target for
the intent is not found. This will ensure the button is not
visible in cases when clicking it would have done nothing.

Bug: 283239837
Flag: com.android.settings.flags.datetime_feedback
Test: Test: atest TimeFeedbackPreferenceControllerTest.java
Change-Id: I8bb18c313925a7dc7ac07a1fb4c2f9e2d98352db
parent 4141fac1
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -19,9 +19,12 @@ package com.android.settings.datetime;
import static android.content.Intent.URI_INTENT_SCHEME;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.preference.Preference;

@@ -40,17 +43,22 @@ public class TimeFeedbackPreferenceController
        extends BasePreferenceController
        implements PreferenceControllerMixin {

    private static final String TAG = "TimeFeedbackController";

    private final PackageManager mPackageManager;
    private final String mIntentUri;
    private final int mAvailabilityStatus;

    public TimeFeedbackPreferenceController(Context context, String preferenceKey) {
        this(context, preferenceKey, context.getResources().getString(
        this(context, context.getPackageManager(), preferenceKey, context.getResources().getString(
                R.string.config_time_feedback_intent_uri));
    }

    @VisibleForTesting
    TimeFeedbackPreferenceController(Context context, String preferenceKey, String intentUri) {
    TimeFeedbackPreferenceController(Context context, PackageManager packageManager,
            String preferenceKey, String intentUri) {
        super(context, preferenceKey);
        mPackageManager = packageManager;
        mIntentUri = intentUri;
        mAvailabilityStatus = TextUtils.isEmpty(mIntentUri) ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
    }
@@ -70,6 +78,9 @@ public class TimeFeedbackPreferenceController
        if (!DateTimeLaunchUtils.isFeedbackFeatureSupported()) {
            return UNSUPPORTED_ON_DEVICE;
        }
        if (!isTimeFeedbackTargetAvailable()) {
            return CONDITIONALLY_UNAVAILABLE;
        }
        return mAvailabilityStatus;
    }

@@ -89,7 +100,25 @@ public class TimeFeedbackPreferenceController
            mContext.startActivity(intent);
            return true;
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException("Bad intent configuration: " + mIntentUri, e);
            Log.e(TAG, "Bad intent configuration: " + mIntentUri, e);
            return false;
        }
    }

    private boolean isTimeFeedbackTargetAvailable() {
        Intent intent;
        try {
            intent = Intent.parseUri(mIntentUri, URI_INTENT_SCHEME);
        } catch (URISyntaxException e) {
            Log.e(TAG, "Bad intent configuration: " + mIntentUri, e);
            return false;
        }
        ComponentName resolvedActivity = intent.resolveActivity(mPackageManager);

        if (resolvedActivity == null) {
            Log.w(TAG, "No valid target for the time feedback intent: " + intent);
            return false;
        }
        return true;
    }
}
+78 −7
Original line number Diff line number Diff line
@@ -16,31 +16,64 @@

package com.android.settings.datetime;

import static android.provider.DeviceConfig.NAMESPACE_SETTINGS_UI;

import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;

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

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.DeviceConfig;

import androidx.preference.Preference;

import com.android.settings.flags.Flags;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class TimeFeedbackPreferenceControllerTest {

    private static final String PACKAGE = "com.android.settings.test";
    private static final String TEST_INTENT_URI =
            "intent:#Intent;"
                    + "action=com.android.settings.test.LAUNCH_USER_FEEDBACK;"
                    + "package=com.android.settings.test.target;"
                    + "end";

    @Rule
    public final MockitoRule mMockitoRule = MockitoJUnit.rule();

    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    @Mock
    private PackageManager mMockPackageManager;
    private Context mContext;

    @Before
@@ -52,21 +85,47 @@ public class TimeFeedbackPreferenceControllerTest {
    public void emptyIntentUri_controllerNotAvailable() {
        String emptyIntentUri = "";
        TimeFeedbackPreferenceController controller =
                new TimeFeedbackPreferenceController(mContext, "test_key", emptyIntentUri);
                new TimeFeedbackPreferenceController(mContext, mContext.getPackageManager(),
                        "test_key", emptyIntentUri);
        assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
    }

    @Test
    @EnableFlags({Flags.FLAG_DATETIME_FEEDBACK})
    public void validIntentUri_targetHandlerNotFound_returnsConditionallyUnavailable() {
        DeviceConfig.setProperty(NAMESPACE_SETTINGS_UI,
                DateTimeLaunchUtils.KEY_HELP_AND_FEEDBACK_FEATURE_SUPPORTED, "true", true);
        when(mMockPackageManager.resolveActivity(any(), anyInt())).thenReturn(null);

        TimeFeedbackPreferenceController controller =
                new TimeFeedbackPreferenceController(mContext, mMockPackageManager, "test_key",
                        TEST_INTENT_URI);

        assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
    }

    @Test
    @EnableFlags({Flags.FLAG_DATETIME_FEEDBACK})
    public void validIntentUri_targetHandlerAvailable_returnsAvailable() {
        DeviceConfig.setProperty(NAMESPACE_SETTINGS_UI,
                DateTimeLaunchUtils.KEY_HELP_AND_FEEDBACK_FEATURE_SUPPORTED, "true", true);
        when(mMockPackageManager.resolveActivity(any(), anyInt())).thenReturn(
                createDummyResolveInfo());

        TimeFeedbackPreferenceController controller =
                new TimeFeedbackPreferenceController(mContext, mMockPackageManager, "test_key",
                        TEST_INTENT_URI);

        assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
    }

    @Test
    public void clickPreference() {
        Preference preference = new Preference(mContext);

        String intentUri =
                "intent:#Intent;"
                        + "action=com.android.settings.test.LAUNCH_USER_FEEDBACK;"
                        + "package=com.android.settings.test.target;"
                        + "end";
        TimeFeedbackPreferenceController controller =
                new TimeFeedbackPreferenceController(mContext, "test_key", intentUri);
                new TimeFeedbackPreferenceController(mContext, mContext.getPackageManager(),
                        "test_key", TEST_INTENT_URI);

        // Click a preference that's not controlled by this controller.
        preference.setKey("fake_key");
@@ -87,4 +146,16 @@ public class TimeFeedbackPreferenceControllerTest {
                "com.android.settings.test.LAUNCH_USER_FEEDBACK");
        assertThat(actualIntent.getPackage()).isEqualTo("com.android.settings.test.target");
    }

    private static ResolveInfo createDummyResolveInfo() {
        ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.packageName = PACKAGE;
        ActivityInfo activityInfo = new ActivityInfo();
        activityInfo.applicationInfo = applicationInfo;
        activityInfo.name = "TestActivity";

        ResolveInfo resolveInfo = new ResolveInfo();
        resolveInfo.activityInfo = activityInfo;
        return resolveInfo;
    }
}