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

Commit 92d016c9 authored by Tracy Zhou's avatar Tracy Zhou
Browse files

Merging from ub-launcher3-master @ build 6094789

Test: manual, presubmit on the source branch
http://x20/teams/android-launcher/merge/ub-launcher3-master_6094789.html

Change-Id: Ib604bbc8cc3eb5bbaf45c3d3e7598462edfbbc2d
parents 920016a3 5eccd03e
Loading
Loading
Loading
Loading
+55 −7
Original line number Diff line number Diff line
@@ -19,14 +19,18 @@ import static junit.framework.TestCase.fail;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.ContentResolver;
import android.provider.Settings.Secure;

import androidx.annotation.Nullable;

import com.android.customization.model.CustomizationManager.Callback;

import com.android.customization.module.ThemesUserEventLogger;

import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,11 +43,15 @@ import org.robolectric.RuntimeEnvironment;
public class ClockManagerTest {

    private static final String CLOCK_ID = "id";
    private static final String CLOCK_FIELD = "clock";
    private static final String CLOCK_FACE_SETTING = "fake_clock_face_setting";

    @Mock ClockProvider mProvider;
    @Mock ThemesUserEventLogger mLogger;
    private ContentResolver mContentResolver;
    private ClockManager mManager;
    @Mock private Clockface mMockClockface;
    @Mock private Callback mMockCallback;

    @Before
    public void setUp() {
@@ -53,7 +61,7 @@ public class ClockManagerTest {
    }

    @Test
    public void testApply() {
    public void testApply() throws JSONException {
        Clockface clock = new Clockface.Builder().setId(CLOCK_ID).build();

        mManager.apply(clock, new Callback() {
@@ -69,16 +77,56 @@ public class ClockManagerTest {
        });

        // THEN the clock id is written to secure settings.
        assertEquals(CLOCK_ID, Secure.getString(mContentResolver, ClockManager.CLOCK_FACE_SETTING));
        JSONObject json =
                new JSONObject(Secure.getString(mContentResolver, ClockManager.CLOCK_FACE_SETTING));
        assertEquals(CLOCK_ID, json.getString(CLOCK_FIELD));
        // AND the event is logged
        verify(mLogger).logClockApplied(clock);
    }

    @Test
    public void testGetCurrentClock() {
        // GIVEN that secure settings contains a clock id
        Secure.putString(mContentResolver, ClockManager.CLOCK_FACE_SETTING, CLOCK_ID);
        // THEN the current clock is that id
    public void testApply_whenJSONExceptionOccurs_callsOnError() {
        when(mMockClockface.getId()).thenThrow(JSONException.class);

        mManager.apply(mMockClockface, mMockCallback);

        verify(mMockCallback).onError(null);
    }

    @Test
    public void testGetCurrentClock_returnsClockId() throws JSONException {
        // Secure settings contains a clock id
        JSONObject json = new JSONObject().put(CLOCK_FIELD, CLOCK_ID);
        Secure.putString(mContentResolver, ClockManager.CLOCK_FACE_SETTING, json.toString());

        // The current clock is that id
        assertEquals(CLOCK_ID, mManager.getCurrentClock());
    }

    @Test
    public void testGetCurrentClock_whenJSONExceptionOccurs_returnsClockFaceSetting() {
        // Secure settings contains a clock face setting with invalid format to cause JSONException.
        Secure.putString(mContentResolver, ClockManager.CLOCK_FACE_SETTING, CLOCK_FACE_SETTING);

        // The current clock is the clock face setting which is saved in secure settings.
        assertEquals(CLOCK_FACE_SETTING, mManager.getCurrentClock());
    }

    @Test
    public void testGetCurrentClock_withNullIdInSecureSettings_returnsNullId() {
        // Secure settings contains a null clock id
        Secure.putString(mContentResolver, ClockManager.CLOCK_FACE_SETTING, /* value= */ null);

        // The current clock is null
        assertEquals(null, mManager.getCurrentClock());
    }

    @Test
    public void testGetCurrentClock_withEmptyIdInSecureSettings_returnsEmptyId() {
        // Secure settings contains an empty clock id
        Secure.putString(mContentResolver, ClockManager.CLOCK_FACE_SETTING, /* value= */ "");

        // The current clock is empty
        assertEquals("", mManager.getCurrentClock());
    }
}
+95 −17
Original line number Diff line number Diff line
@@ -26,25 +26,28 @@ import static com.android.customization.model.ResourceConstants.SETTINGS_PACKAGE
import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
import static com.android.customization.model.ResourceConstants.THEME_SETTING;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;

import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.provider.Settings;

import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;

import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
import com.android.customization.model.CustomizationManager.Callback;
import com.android.customization.model.theme.custom.CustomTheme;
import com.android.customization.module.ThemesUserEventLogger;
import com.android.customization.testutils.OverlayManagerMocks;
import com.android.customization.testutils.Wait;
import com.android.wallpaper.module.WallpaperSetter;

import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -60,6 +63,7 @@ public class ThemeManagerTest {
    @Mock OverlayManagerCompat mMockOm;
    @Mock WallpaperSetter mMockWallpaperSetter;
    @Mock ThemesUserEventLogger mThemesUserEventLogger;
    @Mock ThemeBundleProvider mThemeBundleProvider;
    private OverlayManagerMocks mMockOmHelper;
    private ThemeManager mThemeManager;
    private FragmentActivity mActivity;
@@ -71,9 +75,8 @@ public class ThemeManagerTest {
        mActivity = spy(activity);
        mMockOmHelper = new OverlayManagerMocks();
        mMockOmHelper.setUpMock(mMockOm);
        ThemeBundleProvider provider = mock(ThemeBundleProvider.class);
        mThemeManager = new ThemeManager(
                provider, activity, mMockWallpaperSetter, mMockOm, mThemesUserEventLogger);
        mThemeManager = new ThemeManager(mThemeBundleProvider, activity, mMockWallpaperSetter,
                mMockOm, mThemesUserEventLogger);
    }

    @After
@@ -82,7 +85,7 @@ public class ThemeManagerTest {
    }

    @Test
    public void testApply_DefaultTheme() {
    public void apply_WithDefaultTheme_StoresEmptyJsonString() {
        mMockOmHelper.addOverlay("test.package.name_color", ANDROID_PACKAGE,
                OVERLAY_CATEGORY_COLOR, true, 0);
        mMockOmHelper.addOverlay("test.package.name_font", ANDROID_PACKAGE,
@@ -102,13 +105,94 @@ public class ThemeManagerTest {

        applyTheme(defaultTheme);

        assertEquals("Secure Setting should be emtpy after applying default theme",
                "",
        assertEquals("Secure Setting should be empty JSON string after applying default theme",
                new JSONObject().toString(),
                Settings.Secure.getString(mActivity.getContentResolver(), THEME_SETTING));
    }

    @Test
    public void testApply_NonDefault() {
    public void apply_WithOverlayTheme_StoresSerializedPackagesWithTimestamp() {
        ThemeBundle theme = getOverlayTheme();
        final String serializedPackagesWithTimestamp = theme.getSerializedPackagesWithTimestamp();

        theme = spy(theme);
        // Makes it return the fixed serializedPackagesWithTimestamp to test. Since we will get
        // fresh time every time, it's hard to compare for testing.
        when(theme.getSerializedPackagesWithTimestamp())
                .thenReturn(serializedPackagesWithTimestamp);

        applyTheme(theme);

        assertEquals("Secure Setting should be the overlay packages after applying theme",
                serializedPackagesWithTimestamp,
                Settings.Secure.getString(mActivity.getContentResolver(), THEME_SETTING));
    }

    @Test
    public void isAvailable_ThemeBundleProviderAndOverlayManagerAreAvailable_ReturnsTrue() {
        when(mThemeBundleProvider.isAvailable()).thenReturn(true);
        when(mMockOm.isAvailable()).thenReturn(true);

        assertTrue(mThemeManager.isAvailable());
    }

    @Test
    public void isAvailable_ThemeBundleProviderOrOverlayManagerIsAvailable_ReturnsFalse() {
        when(mThemeBundleProvider.isAvailable()).thenReturn(false);
        when(mMockOm.isAvailable()).thenReturn(true);
        assertFalse(mThemeManager.isAvailable());

        when(mThemeBundleProvider.isAvailable()).thenReturn(true);
        when(mMockOm.isAvailable()).thenReturn(false);
        assertFalse(mThemeManager.isAvailable());
    }

    @Test
    public void fetchOptions_ThemeBundleProviderFetches() {
        OptionsFetchedListener listener = mock(OptionsFetchedListener.class);

        mThemeManager.fetchOptions(listener, false);

        verify(mThemeBundleProvider).fetch(listener, false);
    }

    @Test
    public void removeCustomTheme_ThemeBundleProviderRemovesCustomTheme() {
        CustomTheme customTheme = mock(CustomTheme.class);
        mThemeManager.removeCustomTheme(customTheme);

        verify(mThemeBundleProvider).removeCustomTheme(customTheme);
    }

    @Test
    public void findThemeByPackages_ThemeBundleProviderFindsEquivalent() {
        CustomTheme theme = mock(CustomTheme.class);
        mThemeManager.findThemeByPackages(theme);

        verify(mThemeBundleProvider).findEquivalent(theme);
    }

    @Test
    public void storeEmptyTheme_SettingsSecureStoresEmptyTheme() {
        mThemeManager.storeEmptyTheme();

        assertEquals(
                new JSONObject().toString(),
                Settings.Secure.getString(mActivity.getContentResolver(), THEME_SETTING));
    }

    @Test
    public void getStoredOverlays_GetsFromSettingsSecureWithExpectedName() {
        ThemeBundle theme = getOverlayTheme();

        applyTheme(theme);

        assertEquals(
                Settings.Secure.getString(mActivity.getContentResolver(), THEME_SETTING),
                mThemeManager.getStoredOverlays());
    }

    private ThemeBundle getOverlayTheme() {
        final String bundleColorPackage = "test.package.name_color";
        final String bundleFontPackage = "test.package.name_font";
        final String otherPackage = "other.package.name_font";
@@ -120,16 +204,10 @@ public class ThemeManagerTest {
        mMockOmHelper.addOverlay(otherPackage, ANDROID_PACKAGE,
                OVERLAY_CATEGORY_FONT, false, 0);

        ThemeBundle theme = new ThemeBundle.Builder()
        return new ThemeBundle.Builder()
                .addOverlayPackage(OVERLAY_CATEGORY_COLOR, bundleColorPackage)
                .addOverlayPackage(OVERLAY_CATEGORY_FONT, bundleFontPackage)
                .build(mActivity);

        applyTheme(theme);

        assertEquals("Secure Setting was not properly set after applying theme",
                theme.getSerializedPackages(),
                Settings.Secure.getString(mActivity.getContentResolver(), THEME_SETTING));
    }

    private void applyTheme(ThemeBundle theme) {
+5 −3
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.view.MenuItem;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
@@ -86,9 +87,10 @@ public class CustomizationPickerActivity extends FragmentActivity implements Wal
        CategoryFragmentHost, ThemeFragmentHost, GridFragmentHost, ClockFragmentHost {

    private static final String TAG = "CustomizationPickerActivity";
    private static final String WALLPAPER_FLAVOR_EXTRA = "com.android.launcher3.WALLPAPER_FLAVOR";
    private static final String WALLPAPER_FOCUS = "focus_wallpaper";
    private static final String WALLPAPER_ONLY = "wallpaper_only";
    @VisibleForTesting static final String WALLPAPER_FLAVOR_EXTRA =
            "com.android.launcher3.WALLPAPER_FLAVOR";
    @VisibleForTesting static final String WALLPAPER_FOCUS = "focus_wallpaper";
    @VisibleForTesting static final String WALLPAPER_ONLY = "wallpaper_only";

    private WallpaperPickerDelegate mDelegate;
    private UserEventLogger mUserEventLogger;
+160 −0
Original line number Diff line number Diff line
package com.android.customization.picker;

import static android.content.Intent.ACTION_SET_WALLPAPER;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.intent.matcher.IntentMatchers.filterEquals;
import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isSelected;
import static androidx.test.espresso.matcher.ViewMatchers.withId;

import static com.android.customization.picker.CustomizationPickerActivity.WALLPAPER_FLAVOR_EXTRA;
import static com.android.customization.picker.CustomizationPickerActivity.WALLPAPER_FOCUS;
import static com.android.customization.picker.CustomizationPickerActivity.WALLPAPER_ONLY;

import static org.junit.Assert.assertTrue;

import android.content.Intent;
import android.text.TextUtils;

import androidx.fragment.app.Fragment;
import androidx.test.espresso.intent.Intents;
import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
import androidx.test.rule.ActivityTestRule;

import com.android.customization.picker.theme.ThemeFragment;
import com.android.customization.testing.TestCustomizationInjector;
import com.android.customization.testing.TestThemeManager;
import com.android.wallpaper.R;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.picker.CategoryFragment;
import com.android.wallpaper.picker.TopLevelPickerActivity;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Tests for {@link CustomizationPickerActivity}.
 */
@RunWith(AndroidJUnit4ClassRunner.class)
public class CustomizationPickerActivityTest {

    @Rule
    public ActivityTestRule<CustomizationPickerActivity> mActivityRule =
            new ActivityTestRule<>(CustomizationPickerActivity.class, false, false);

    @Before
    public void setUp() {
        Intents.init();
    }

    @After
    public void tearDown() {
        mActivityRule.finishActivity();
        Intents.release();
    }

    @Test
    public void launchActivity_doesNotSupportCustomization_launchesTopLevelPickerActivity() {
        TestThemeManager.setAvailable(false);

        launchActivity();

        Intents.intended(filterEquals(new Intent(mActivityRule.getActivity(),
                TopLevelPickerActivity.class)));
    }

    // ----------------------------------------------------------------------
    // Tests for customization supports.
    // ----------------------------------------------------------------------

    @Test
    public void launchActivity_themeManagerIsAvailable_NavBarShowsStyleAndWallpaperItem() {
        TestThemeManager.setAvailable(true);

        launchActivity();

        onView(withId(R.id.nav_theme)).check(matches(isCompletelyDisplayed()));
        onView(withId(R.id.nav_wallpaper)).check(matches(isCompletelyDisplayed()));
        onView(withId(R.id.nav_clock)).check(doesNotExist());
        onView(withId(R.id.nav_grid)).check(doesNotExist());
    }

    @Test
    public void launchActivity_navigateToTheStyleTabByDefault() {
        TestThemeManager.setAvailable(true);

        launchActivity();

        onView(withId(R.id.nav_theme)).check(matches(isSelected()));
        assertTrue(getCurrentShowingFragment() instanceof ThemeFragment);
    }

    @Test
    public void launchActivity_withExtraWallpaperOnly_launchesTopLevelPickerActivity() {
        TestThemeManager.setAvailable(true);

        launchActivityWithFlavorExtra(WALLPAPER_ONLY);

        // While receiving WALLPAPER_ONLY extra, it should launch TopLevelPickerActivity whatever it
        // supports customization.
        Intents.intended(filterEquals(new Intent(mActivityRule.getActivity(),
                TopLevelPickerActivity.class)));
    }

    @Test
    public void clickStyleButton_showsThemeFragment() {
        TestThemeManager.setAvailable(true);
        launchActivity();

        onView(withId(R.id.nav_theme)).perform(click());

        onView(withId(R.id.nav_theme)).check(matches(isSelected()));
        assertTrue(getCurrentShowingFragment() instanceof ThemeFragment);
    }

    @Test
    public void clickWallpaperButton_showsCategoryFragment() {
        TestThemeManager.setAvailable(true);
        launchActivity();

        onView(withId(R.id.nav_wallpaper)).perform(click());

        onView(withId(R.id.nav_wallpaper)).check(matches(isSelected()));
        assertTrue(getCurrentShowingFragment() instanceof CategoryFragment);
    }

    @Test
    public void launchActivity_withExtraWallpaperFocus_navigateToTheWallpaperTab() {
        TestThemeManager.setAvailable(true);

        launchActivityWithFlavorExtra(WALLPAPER_FOCUS);

        onView(withId(R.id.nav_wallpaper)).check(matches(isSelected()));
        assertTrue(getCurrentShowingFragment() instanceof CategoryFragment);
    }

    private void launchActivity() {
        launchActivityWithFlavorExtra("");
    }

    private void launchActivityWithFlavorExtra(String extra) {
        InjectorProvider.setInjector(new TestCustomizationInjector());
        Intent intent = new Intent(ACTION_SET_WALLPAPER);
        if (!TextUtils.isEmpty(extra)) {
            intent.putExtra(WALLPAPER_FLAVOR_EXTRA, extra);
        }
        mActivityRule.launchActivity(intent);
    }

    private Fragment getCurrentShowingFragment() {
        return mActivityRule.getActivity().getSupportFragmentManager()
                .findFragmentById(R.id.fragment_container);
    }
}
+74 −0
Original line number Diff line number Diff line
package com.android.customization.testing;

import android.content.Context;

import androidx.fragment.app.FragmentActivity;

import com.android.customization.model.theme.OverlayManagerCompat;
import com.android.customization.model.theme.ThemeBundleProvider;
import com.android.customization.model.theme.ThemeManager;
import com.android.customization.module.CustomizationInjector;
import com.android.customization.module.CustomizationPreferences;
import com.android.customization.module.ThemesUserEventLogger;
import com.android.wallpaper.module.DrawableLayerResolver;
import com.android.wallpaper.module.PackageStatusNotifier;
import com.android.wallpaper.module.UserEventLogger;
import com.android.wallpaper.module.WallpaperSetter;
import com.android.wallpaper.testing.TestInjector;

/**
 * Test implementation of the dependency injector.
 */
public class TestCustomizationInjector extends TestInjector implements CustomizationInjector {
    private CustomizationPreferences mCustomizationPreferences;
    private ThemeManager mThemeManager;
    private PackageStatusNotifier mPackageStatusNotifier;
    private DrawableLayerResolver mDrawableLayerResolver;
    private UserEventLogger mUserEventLogger;

    @Override
    public CustomizationPreferences getCustomizationPreferences(Context context) {
        if (mCustomizationPreferences == null) {
            mCustomizationPreferences = new TestDefaultCustomizationPreferences(context);
        }
        return mCustomizationPreferences;
    }

    @Override
    public ThemeManager getThemeManager(
            ThemeBundleProvider provider,
            FragmentActivity activity,
            WallpaperSetter wallpaperSetter,
            OverlayManagerCompat overlayManagerCompat,
            ThemesUserEventLogger logger) {
        if (mThemeManager == null) {
            mThemeManager = new TestThemeManager(provider, activity, wallpaperSetter,
                    overlayManagerCompat, logger);
        }
        return mThemeManager;
    }

    @Override
    public PackageStatusNotifier getPackageStatusNotifier(Context context) {
        if (mPackageStatusNotifier == null) {
            mPackageStatusNotifier =  new TestPackageStatusNotifier();
        }
        return mPackageStatusNotifier;
    }

    @Override
    public DrawableLayerResolver getDrawableLayerResolver() {
        if (mDrawableLayerResolver == null) {
            mDrawableLayerResolver = new TestDrawableLayerResolver();
        }
        return mDrawableLayerResolver;
    }

    @Override
    public UserEventLogger getUserEventLogger(Context unused) {
        if (mUserEventLogger == null) {
            mUserEventLogger = new TestThemesUserEventLogger();
        }
        return mUserEventLogger;
    }
}
Loading