diff --git a/src/com/android/settings/homepage/CardContentLoader.java b/src/com/android/settings/homepage/CardContentLoader.java index 9805ae3e409..5b81a2381f0 100644 --- a/src/com/android/settings/homepage/CardContentLoader.java +++ b/src/com/android/settings/homepage/CardContentLoader.java @@ -17,16 +17,21 @@ package com.android.settings.homepage; import android.content.Context; +import android.content.pm.PackageManager; import android.database.Cursor; +import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import com.android.settings.homepage.deviceinfo.DataUsageSlice; import com.android.settingslib.utils.AsyncLoaderCompat; import java.util.ArrayList; import java.util.List; public class CardContentLoader extends AsyncLoaderCompat> { + private static final String TAG = "CardContentLoader"; static final int CARD_CONTENT_LOADER_ID = 1; private Context mContext; @@ -49,9 +54,9 @@ public class CardContentLoader extends AsyncLoaderCompat> { @Override public List loadInBackground() { final List result = new ArrayList<>(); - try (Cursor cursor = CardDatabaseHelper.getInstance(mContext).getContextualCards()) { + try (Cursor cursor = getContextualCardsFromProvider()) { if (cursor.getCount() == 0) { - //TODO(b/113372471): Load Default static cards and return 3 static cards + result.addAll(createStaticCards()); return result; } for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { @@ -65,4 +70,58 @@ public class CardContentLoader extends AsyncLoaderCompat> { } return result; } + + @VisibleForTesting + Cursor getContextualCardsFromProvider() { + return CardDatabaseHelper.getInstance(mContext).getContextualCards(); + } + + @VisibleForTesting + List createStaticCards() { + final long appVersionCode = getAppVersionCode(); + final String packageName = mContext.getPackageName(); + final double rankingScore = 0.0; + final List result = new ArrayList() {{ + add(new ContextualCard.Builder() + .setSliceUri(DataUsageSlice.DATA_USAGE_CARD_URI.toString()) + .setName(packageName + "/" + DataUsageSlice.PATH_DATA_USAGE_CARD) + .setPackageName(packageName) + .setRankingScore(rankingScore) + .setAppVersion(appVersionCode) + .setCardType(ContextualCard.CardType.SLICE) + .setIsHalfWidth(true) + .build()); + //TODO(b/115971399): Will change following values of SliceUri and Name + // after landing these slice cards. + add(new ContextualCard.Builder() + .setSliceUri("content://com.android.settings.slices/intent/battery_card") + .setName(packageName + "/" + "battery_card") + .setPackageName(packageName) + .setRankingScore(rankingScore) + .setAppVersion(appVersionCode) + .setCardType(ContextualCard.CardType.SLICE) + .setIsHalfWidth(true) + .build()); + add(new ContextualCard.Builder() + .setSliceUri("content://com.android.settings.slices/intent/device_info_card") + .setName(packageName + "/" + "device_info_card") + .setPackageName(packageName) + .setRankingScore(rankingScore) + .setAppVersion(appVersionCode) + .setCardType(ContextualCard.CardType.SLICE) + .setIsHalfWidth(true) + .build()); + }}; + return result; + } + + private long getAppVersionCode() { + try { + return mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), + 0 /* flags */).getLongVersionCode(); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Invalid package name for context", e); + } + return -1L; + } } diff --git a/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java new file mode 100644 index 00000000000..20ad067ae15 --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java @@ -0,0 +1,145 @@ +/* + * 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.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.database.Cursor; +import android.database.MatrixCursor; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; + +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +public class CardContentLoaderTest { + private static final String[] QUERY_PROJECTION = { + CardDatabaseHelper.CardColumns.NAME, + CardDatabaseHelper.CardColumns.TYPE, + CardDatabaseHelper.CardColumns.SCORE, + CardDatabaseHelper.CardColumns.SLICE_URI, + CardDatabaseHelper.CardColumns.CATEGORY, + CardDatabaseHelper.CardColumns.LOCALIZED_TO_LOCALE, + CardDatabaseHelper.CardColumns.PACKAGE_NAME, + CardDatabaseHelper.CardColumns.APP_VERSION, + CardDatabaseHelper.CardColumns.TITLE_RES_NAME, + CardDatabaseHelper.CardColumns.TITLE_TEXT, + CardDatabaseHelper.CardColumns.SUMMARY_RES_NAME, + CardDatabaseHelper.CardColumns.SUMMARY_TEXT, + CardDatabaseHelper.CardColumns.ICON_RES_NAME, + CardDatabaseHelper.CardColumns.ICON_RES_ID, + CardDatabaseHelper.CardColumns.CARD_ACTION, + CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS, + CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH + }; + + private Context mContext; + private CardContentLoader mCardContentLoader; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mCardContentLoader = spy(new CardContentLoader(mContext)); + } + + @Test + public void loadInBackground_hasDataInDb_shouldReturnData() { + final Cursor cursor = generateTwoRowContextualCards(); + doReturn(cursor).when(mCardContentLoader).getContextualCardsFromProvider(); + + final List contextualCards = mCardContentLoader.loadInBackground(); + + assertThat(contextualCards.size()).isEqualTo(cursor.getCount()); + } + + @Test + public void loadInBackground_hasNoData_shouldReturnThreeDefaultData() { + final Cursor cursor = generateEmptyContextualCards(); + doReturn(cursor).when(mCardContentLoader).getContextualCardsFromProvider(); + + final List contextualCards = mCardContentLoader.loadInBackground(); + + assertThat(contextualCards.size()).isEqualTo(mCardContentLoader.createStaticCards().size()); + } + + private MatrixCursor generateEmptyContextualCards() { + final MatrixCursor result = new MatrixCursor(QUERY_PROJECTION); + return result; + } + + private MatrixCursor generateTwoRowContextualCards() { + final MatrixCursor result = generateEmptyContextualCards(); + result.addRow(generateFirstFakeData()); + result.addRow(generateSecondFakeData()); + return result; + } + + private Object[] generateFirstFakeData() { + final Object[] ref = new Object[]{ + "auto_rotate", /* NAME */ + ContextualCard.CardType.SLICE, /* TYPE */ + 0.5, /* SCORE */ + "content://com.android.settings.slices/action/auto_rotate", /* SLICE_URI */ + 2, /* CATEGORY */ + "", /* LOCALIZED_TO_LOCALE */ + "com.android.settings", /* PACKAGE_NAME */ + 1l, /* APP_VERSION */ + "", /* TITLE_RES_NAME */ + "", /* TITLE_TEXT */ + "", /* SUMMARY_RES_NAME */ + "", /* SUMMARY_TEXT */ + "", /* ICON_RES_NAME */ + 0, /* ICON_RES_ID */ + 0, /* CARD_ACTION */ + -1, /* EXPIRE_TIME_MS */ + 0 /* SUPPORT_HALF_WIDTH */ + }; + return ref; + } + + private Object[] generateSecondFakeData() { + final Object[] ref = new Object[]{ + "toggle_airplane", /* NAME */ + ContextualCard.CardType.SLICE, /* TYPE */ + 0.5, /* SCORE */ + "content://com.android.settings.slices/action/toggle_airplane", /* SLICE_URI */ + 2, /* CATEGORY */ + "", /* LOCALIZED_TO_LOCALE */ + "com.android.settings", /* PACKAGE_NAME */ + 1l, /* APP_VERSION */ + "", /* TITLE_RES_NAME */ + "", /* TITLE_TEXT */ + "", /* SUMMARY_RES_NAME */ + "", /* SUMMARY_TEXT */ + "", /* ICON_RES_NAME */ + 0, /* ICON_RES_ID */ + 0, /* CARD_ACTION */ + -1, /* EXPIRE_TIME_MS */ + 0 /* SUPPORT_HALF_WIDTH */ + }; + return ref; + } +} diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/unit/src/com/android/settings/homepage/SettingsHomepageActivityTest.java similarity index 68% rename from tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java rename to tests/unit/src/com/android/settings/homepage/SettingsHomepageActivityTest.java index 4b237a0e0ed..89ec476ed4c 100644 --- a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java +++ b/tests/unit/src/com/android/settings/homepage/SettingsHomepageActivityTest.java @@ -16,25 +16,28 @@ package com.android.settings.homepage; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + import static com.android.settings.homepage.SettingsHomepageActivity.PERSONAL_SETTINGS_TAG; import static com.google.common.truth.Truth.assertThat; import android.content.Context; +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; import android.util.FeatureFlagUtils; import androidx.fragment.app.Fragment; import com.android.settings.core.FeatureFlags; -import com.android.settings.testutils.SettingsRobolectricTestRunner; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.Robolectric; -import org.robolectric.RuntimeEnvironment; -@RunWith(SettingsRobolectricTestRunner.class) +@RunWith(AndroidJUnit4.class) public class SettingsHomepageActivityTest { private Context mContext; @@ -42,16 +45,27 @@ public class SettingsHomepageActivityTest { @Before public void setUp() { - mContext = RuntimeEnvironment.application; + mContext = InstrumentationRegistry.getTargetContext(); FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DYNAMIC_HOMEPAGE, true); } + @After + public void tearDown() { + FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DYNAMIC_HOMEPAGE, false); + } + @Test public void launchHomepage_shouldOpenPersonalSettings() { - mActivity = Robolectric.setupActivity(SettingsHomepageActivity.class); + final Intent intent = new Intent().setClass(mContext, SettingsHomepageActivity.class) + .addFlags(FLAG_ACTIVITY_NEW_TASK); + + mActivity = (SettingsHomepageActivity) InstrumentationRegistry.getInstrumentation() + .startActivitySync(intent); + final Fragment fragment = mActivity.getSupportFragmentManager() .findFragmentByTag(PERSONAL_SETTINGS_TAG); assertThat(fragment).isInstanceOf(PersonalSettingsFragment.class); } + }