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

Commit 22e56834 authored by Kanyinsola Fapohunda's avatar Kanyinsola Fapohunda Committed by Android (Google) Code Review
Browse files

Merge changes from topic "feedback_and_help" into main

* changes:
  Hide "Send feedback" button if no target exists.
  Move "Send feedback" button to the end of the list
parents c6675e54 8c427e65
Loading
Loading
Loading
Loading
+12 −13
Original line number Diff line number Diff line
@@ -90,7 +90,18 @@

    </PreferenceCategory>

    <!-- An optional preference category for feedback. Only displayed up if enabled via flags and config. -->
    <PreferenceCategory
        android:key="time_format_preference_category"
        android:title="@string/time_format_category_title"
        settings:keywords="@string/keywords_time_format">

        <SwitchPreferenceCompat
            android:key="24 hour"
            android:title="@string/date_time_24hour"
            settings:controller="com.android.settings.datetime.TimeFormatPreferenceController" />
    </PreferenceCategory>

    <!-- An optional preference category for feedback. Only displayed up if enabled via flags and config. Always put time feedback at the end. -->
    <PreferenceCategory
        android:key="time_feedback_preference_category"
        android:title="@string/time_feedback_category_title"
@@ -102,18 +113,6 @@
            android:title="@string/time_feedback_title"
            settings:controller="com.android.settings.datetime.TimeFeedbackPreferenceController"
            settings:keywords="@string/keywords_time_feedback" />

    </PreferenceCategory>

    <PreferenceCategory
        android:key="time_format_preference_category"
        android:title="@string/time_format_category_title"
        settings:keywords="@string/keywords_time_format">

        <SwitchPreferenceCompat
            android:key="24 hour"
            android:title="@string/date_time_24hour"
            settings:controller="com.android.settings.datetime.TimeFormatPreferenceController" />
    </PreferenceCategory>

</PreferenceScreen>
+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;
    }
}