diff --git a/AndroidManifest.xml b/AndroidManifest.xml index aa3364fdfbd..c8d9afff9ef 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -124,7 +124,7 @@ android:value="true" /> - + android:targetActivity=".homepage.SettingsHomepageActivity"> diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index cde2aca820c..ffce321a453 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -62,6 +62,7 @@ import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.gateway.SettingsGateway; import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.dashboard.DashboardSummary; +import com.android.settings.homepage.SettingsHomepageActivity; import com.android.settings.homepage.TopLevelSettings; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.DeviceIndexFeatureProvider; diff --git a/src/com/android/settings/homepage/ContextualCardManager.java b/src/com/android/settings/homepage/ContextualCardManager.java index 255f7a218a6..aa2f576ef11 100644 --- a/src/com/android/settings/homepage/ContextualCardManager.java +++ b/src/com/android/settings/homepage/ContextualCardManager.java @@ -28,14 +28,14 @@ import java.util.List; /** * This is a centralized manager of multiple {@link ContextualCardController}. * - * {@link ContextualCardManager} first loads data from {@link CardContentLoader} and gets back a list of - * {@link ContextualCard}. All subclasses of {@link ContextualCardController} are loaded here, which - * will then trigger the {@link ContextualCardController} to load its data and listen to + * {@link ContextualCardManager} first loads data from {@link CardContentLoader} and gets back a + * list of {@link ContextualCard}. All subclasses of {@link ContextualCardController} are loaded + * here, which will then trigger the {@link ContextualCardController} to load its data and listen to * corresponding changes. When every single {@link ContextualCardController} updates its data, the * data will be passed here, then going through some sorting mechanisms. The - * {@link ContextualCardController} will end up building a list of {@link ContextualCard} for {@link - * ContextualCardsAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to get the page - * refreshed. + * {@link ContextualCardController} will end up building a list of {@link ContextualCard} for + * {@link ContextualCardsAdapter} and {@link BaseAdapter#notifyDataSetChanged()} will be called to + * get the page refreshed. */ public class ContextualCardManager implements CardContentLoader.CardContentLoaderListener, ContextualCardUpdateListener { @@ -48,8 +48,8 @@ public class ContextualCardManager implements CardContentLoader.CardContentLoade private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private final Lifecycle mLifecycle; + private final List mContextualCards; - private List mContextualCards; private ContextualCardUpdateListener mListener; @@ -97,7 +97,7 @@ public class ContextualCardManager implements CardContentLoader.CardContentLoade } @Override - public void onHomepageCardUpdated(int cardType, List updateList) { + public void onContextualCardUpdated(int cardType, List updateList) { //TODO(b/112245748): Should implement a DiffCallback. //Keep the old list for comparison. final List prevCards = mContextualCards; @@ -115,13 +115,16 @@ public class ContextualCardManager implements CardContentLoader.CardContentLoade sortCards(); if (mListener != null) { - mListener.onHomepageCardUpdated(ContextualCard.CardType.INVALID, mContextualCards); + mListener.onContextualCardUpdated(ContextualCard.CardType.INVALID, mContextualCards); } } @Override public void onFinishCardLoading(List contextualCards) { - mContextualCards = contextualCards; + mContextualCards.clear(); + if (contextualCards != null) { + mContextualCards.addAll(contextualCards); + } //Force card sorting here in case CardControllers of custom view have nothing to update // for the first launch. diff --git a/src/com/android/settings/homepage/ContextualCardUpdateListener.java b/src/com/android/settings/homepage/ContextualCardUpdateListener.java index 0b454260081..d307a8f563b 100644 --- a/src/com/android/settings/homepage/ContextualCardUpdateListener.java +++ b/src/com/android/settings/homepage/ContextualCardUpdateListener.java @@ -19,13 +19,13 @@ package com.android.settings.homepage; import java.util.List; /** - * When {@link ContextualCardController} detects changes, it will notify the listeners registered. In - * our case, {@link ContextualCardManager} gets noticed. + * When {@link ContextualCardController} detects changes, it will notify the listeners registered. + * In our case, {@link ContextualCardManager} gets noticed. * * After the list of {@link ContextualCard} gets updated in{@link ContextualCardManager}, - * {@link ContextualCardManager} will notify the listeners registered, {@link ContextualCardsAdapter} in this - * case. + * {@link ContextualCardManager} will notify the listeners registered, {@link + * ContextualCardsAdapter} in this case. */ public interface ContextualCardUpdateListener { - void onHomepageCardUpdated(int cardType, List updateList); + void onContextualCardUpdated(int cardType, List updateList); } \ No newline at end of file diff --git a/src/com/android/settings/homepage/ContextualCardsAdapter.java b/src/com/android/settings/homepage/ContextualCardsAdapter.java index 254f4a4b440..e985343cd59 100644 --- a/src/com/android/settings/homepage/ContextualCardsAdapter.java +++ b/src/com/android/settings/homepage/ContextualCardsAdapter.java @@ -37,8 +37,7 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter mContextualCards; + private final List mContextualCards; public ContextualCardsAdapter(Context context, ContextualCardManager manager) { mContext = context; @@ -102,13 +101,14 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter contextualCards) { + public void onContextualCardUpdated(int cardType, List contextualCards) { //TODO(b/112245748): Should implement a DiffCallback so we can use notifyItemChanged() // instead. if (contextualCards == null) { mContextualCards.clear(); } else { - mContextualCards = contextualCards; + mContextualCards.clear(); + mContextualCards.addAll(contextualCards); } notifyDataSetChanged(); } diff --git a/src/com/android/settings/homepage/PersonalSettingsFragment.java b/src/com/android/settings/homepage/PersonalSettingsFragment.java index 69af23be2c8..2eb9663cfda 100644 --- a/src/com/android/settings/homepage/PersonalSettingsFragment.java +++ b/src/com/android/settings/homepage/PersonalSettingsFragment.java @@ -24,7 +24,6 @@ import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -50,11 +49,10 @@ public class PersonalSettingsFragment extends InstrumentedFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - final View rootView = inflater.inflate(R.layout.settings_homepage, - container, false); + final View rootView = inflater.inflate(R.layout.settings_homepage, container, false); mCardsContainer = rootView.findViewById(R.id.card_container); mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT, - LinearLayoutManager.VERTICAL, false /* reverseLayout */); + GridLayoutManager.VERTICAL, false /* reverseLayout */); mCardsContainer.setLayoutManager(mLayoutManager); mContextualCardsAdapter = new ContextualCardsAdapter(getContext(), mContextualCardManager); mCardsContainer.setAdapter(mContextualCardsAdapter); diff --git a/src/com/android/settings/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java similarity index 79% rename from src/com/android/settings/SettingsHomepageActivity.java rename to src/com/android/settings/homepage/SettingsHomepageActivity.java index 77155e00000..35b45a4642a 100644 --- a/src/com/android/settings/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -14,32 +14,31 @@ * limitations under the License. */ -package com.android.settings; +package com.android.settings.homepage; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.FeatureFlagUtils; +import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import com.android.settings.R; import com.android.settings.core.FeatureFlags; import com.android.settings.core.SettingsBaseActivity; -import com.android.settings.dashboard.DashboardSummary; -import com.android.settings.homepage.PersonalSettingsFragment; -import com.android.settings.homepage.TopLevelSettings; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.search.SearchFeatureProvider; import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.floatingactionbutton.FloatingActionButton; public class SettingsHomepageActivity extends SettingsBaseActivity { + @VisibleForTesting + static final String PERSONAL_SETTINGS_TAG = "personal_settings"; private static final String ALL_SETTINGS_TAG = "all_settings"; - private static final String PERSONAL_SETTINGS_TAG = "personal_settings"; @Override protected void onCreate(Bundle savedInstanceState) { @@ -63,25 +62,31 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { navigation.setOnNavigationItemSelectedListener(item -> { switch (item.getItemId()) { case R.id.homepage_personal_settings: - switchFragment(PersonalSettingsFragment.class.getName(), PERSONAL_SETTINGS_TAG, + switchFragment(new PersonalSettingsFragment(), PERSONAL_SETTINGS_TAG, ALL_SETTINGS_TAG); return true; case R.id.homepage_all_settings: - switchFragment(TopLevelSettings.class.getName(), ALL_SETTINGS_TAG, + switchFragment(new TopLevelSettings(), ALL_SETTINGS_TAG, PERSONAL_SETTINGS_TAG); return true; } return false; }); + + if (savedInstanceState == null) { + // savedInstanceState is null, this is first load. + // Default to open contextual cards. + switchFragment(new PersonalSettingsFragment(), PERSONAL_SETTINGS_TAG, + ALL_SETTINGS_TAG); + } } public static boolean isDynamicHomepageEnabled(Context context) { return FeatureFlagUtils.isEnabled(context, FeatureFlags.DYNAMIC_HOMEPAGE); } - private void switchFragment(String fragmentName, String showFragmentTag, - String hideFragmentTag) { + private void switchFragment(Fragment fragment, String showFragmentTag, String hideFragmentTag) { final FragmentManager fragmentManager = getSupportFragmentManager(); final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); @@ -92,8 +97,7 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { Fragment showFragment = fragmentManager.findFragmentByTag(showFragmentTag); if (showFragment == null) { - showFragment = Fragment.instantiate(this, fragmentName, null /* args */); - fragmentTransaction.add(R.id.main_content, showFragment, showFragmentTag); + fragmentTransaction.add(R.id.main_content, fragment, showFragmentTag); } else { fragmentTransaction.show(showFragment); } diff --git a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java index eab6099fff3..6701cfd0196 100644 --- a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java +++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java @@ -58,7 +58,7 @@ public class ConditionContextualCardController implements ContextualCardControll @Override public void onDataUpdated(List cardList) { - mListener.onHomepageCardUpdated(getCardType(), cardList); + mListener.onContextualCardUpdated(getCardType(), cardList); } @Override diff --git a/tests/robotests/res/values/themes.xml b/tests/robotests/res/values/themes.xml index 9a247f6abd8..d3ba69fe292 100644 --- a/tests/robotests/res/values/themes.xml +++ b/tests/robotests/res/values/themes.xml @@ -6,5 +6,14 @@ - diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java new file mode 100644 index 00000000000..4b237a0e0ed --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java @@ -0,0 +1,57 @@ +/* + * 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.homepage; + +import static com.android.settings.homepage.SettingsHomepageActivity.PERSONAL_SETTINGS_TAG; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.util.FeatureFlagUtils; + +import androidx.fragment.app.Fragment; + +import com.android.settings.core.FeatureFlags; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class SettingsHomepageActivityTest { + + private Context mContext; + private SettingsHomepageActivity mActivity; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DYNAMIC_HOMEPAGE, true); + } + + @Test + public void launchHomepage_shouldOpenPersonalSettings() { + mActivity = Robolectric.setupActivity(SettingsHomepageActivity.class); + final Fragment fragment = mActivity.getSupportFragmentManager() + .findFragmentByTag(PERSONAL_SETTINGS_TAG); + + assertThat(fragment).isInstanceOf(PersonalSettingsFragment.class); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java index ad808fcd8db..1432ab1a78a 100644 --- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java +++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java @@ -85,6 +85,8 @@ public class SettingsRobolectricTestRunner extends RobolectricTestRunner { Fs.fromURL(new URL("file:frameworks/opt/setupwizard/library/recyclerview/res")), null)); paths.add(new ResourcePath(null, Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat-nodeps/android_common/aar/res/")), null)); + paths.add(new ResourcePath(null, + Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/extras/material-design-x/com.google.android.material_material-nodeps/android_common/aar/res/")), null)); paths.add(new ResourcePath(null, Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.cardview_cardview-nodeps/android_common/aar/res")), null)); } catch (MalformedURLException e) {