diff --git a/res/xml/data_usage_list.xml b/res/xml/data_usage_list.xml index 28f09c652f3..791fc86647d 100644 --- a/res/xml/data_usage_list.xml +++ b/res/xml/data_usage_list.xml @@ -14,7 +14,8 @@ limitations under the License. --> - + + android:layout="@layout/preference_category_no_label" + settings:controller="com.android.settings.datausage.DataUsageListAppsController" /> diff --git a/src/com/android/settings/datausage/AppDataUsagePreference.java b/src/com/android/settings/datausage/AppDataUsagePreference.java index 28058198d1a..d8c73922b2a 100644 --- a/src/com/android/settings/datausage/AppDataUsagePreference.java +++ b/src/com/android/settings/datausage/AppDataUsagePreference.java @@ -38,6 +38,7 @@ public class AppDataUsagePreference extends AppPreference { public AppDataUsagePreference(Context context, AppItem item, int percent, UidDetailProvider provider) { super(context); + setKey("app_data_usage_" + item.key); mItem = item; mPercent = percent; diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java index b030219d7a8..e4bad128f37 100644 --- a/src/com/android/settings/datausage/DataUsageList.java +++ b/src/com/android/settings/datausage/DataUsageList.java @@ -15,9 +15,7 @@ package com.android.settings.datausage; import android.app.Activity; -import android.app.ActivityManager; import android.app.settings.SettingsEnums; -import android.app.usage.NetworkStats; import android.content.Context; import android.content.Intent; import android.graphics.Color; @@ -46,25 +44,19 @@ import androidx.lifecycle.Lifecycle; import androidx.loader.app.LoaderManager.LoaderCallbacks; import androidx.loader.content.Loader; import androidx.preference.Preference; -import androidx.preference.PreferenceGroup; import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; import com.android.settings.datausage.CycleAdapter.SpinnerInterface; -import com.android.settings.datausage.lib.AppDataUsageRepository; import com.android.settings.network.MobileDataEnabledListener; import com.android.settings.network.MobileNetworkRepository; import com.android.settings.network.ProxySubscriptionManager; import com.android.settings.widget.LoadingViewController; -import com.android.settingslib.AppItem; import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import com.android.settingslib.net.NetworkCycleChartData; import com.android.settingslib.net.NetworkCycleChartDataLoader; -import com.android.settingslib.net.NetworkStatsSummaryLoader; -import com.android.settingslib.net.UidDetailProvider; import com.android.settingslib.utils.ThreadUtils; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -85,14 +77,11 @@ public class DataUsageList extends DataUsageBaseFragment private static final String KEY_USAGE_AMOUNT = "usage_amount"; private static final String KEY_CHART_DATA = "chart_data"; - private static final String KEY_APPS_GROUP = "apps_group"; private static final String KEY_TEMPLATE = "template"; private static final String KEY_APP = "app"; @VisibleForTesting static final int LOADER_CHART_DATA = 2; - @VisibleForTesting - static final int LOADER_SUMMARY = 3; @VisibleForTesting MobileDataEnabledListener mDataStateListener; @@ -113,18 +102,15 @@ public class DataUsageList extends DataUsageBaseFragment @Nullable private List mCycleData; - // Caches the cycles for startAppDataUsage usage, which need be cleared when resumed. - private ArrayList mCycles; // Spinner will keep the selected cycle even after paused, this only keeps the displayed cycle, // which need be cleared when resumed. private CycleAdapter.CycleItem mLastDisplayedCycle; - private UidDetailProvider mUidDetailProvider; private CycleAdapter mCycleAdapter; private Preference mUsageAmount; - private PreferenceGroup mApps; private View mHeader; private MobileNetworkRepository mMobileNetworkRepository; private SubscriptionInfoEntity mSubscriptionInfoEntity; + private DataUsageListAppsController mDataUsageListAppsController; @Override public int getMetricsCategory() { @@ -148,14 +134,19 @@ public class DataUsageList extends DataUsageBaseFragment return; } - mUidDetailProvider = new UidDetailProvider(activity); mUsageAmount = findPreference(KEY_USAGE_AMOUNT); mChart = findPreference(KEY_CHART_DATA); - mApps = findPreference(KEY_APPS_GROUP); processArgument(); + if (mTemplate == null) { + Log.e(TAG, "No template; leaving"); + finish(); + return; + } updateSubscriptionInfoEntity(); mDataStateListener = new MobileDataEnabledListener(activity, this); + mDataUsageListAppsController = use(DataUsageListAppsController.class); + mDataUsageListAppsController.init(mTemplate); } @Override @@ -216,7 +207,6 @@ public class DataUsageList extends DataUsageBaseFragment super.onResume(); mLoadingViewController.showLoadingViewDelayed(); mDataStateListener.start(mSubId); - mCycles = null; mLastDisplayedCycle = null; // kick off loader for network history @@ -234,16 +224,6 @@ public class DataUsageList extends DataUsageBaseFragment mDataStateListener.stop(); getLoaderManager().destroyLoader(LOADER_CHART_DATA); - getLoaderManager().destroyLoader(LOADER_SUMMARY); - } - - @Override - public void onDestroy() { - if (mUidDetailProvider != null) { - mUidDetailProvider.clearCache(); - mUidDetailProvider = null; - } - super.onDestroy(); } @Override @@ -352,6 +332,7 @@ public class DataUsageList extends DataUsageBaseFragment if (mCycleData != null) { mCycleAdapter.updateCycleList(mCycleData); } + mDataUsageListAppsController.setCycleData(mCycleData); updateSelectedCycle(); } @@ -402,67 +383,18 @@ public class DataUsageList extends DataUsageBaseFragment if (LOGD) Log.d(TAG, "updateDetailData()"); // kick off loader for detailed stats - getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */, - mNetworkStatsDetailCallbacks); + mDataUsageListAppsController.update( + mSubscriptionInfoEntity == null ? null : mSubscriptionInfoEntity.carrierId, + mChart.getInspectStart(), + mChart.getInspectEnd() + ); final long totalBytes = mCycleData != null && !mCycleData.isEmpty() - ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0; + ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0; final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes); mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase)); } - /** - * Bind the given buckets. - */ - private void bindStats(List buckets) { - mApps.removeAll(); - AppDataUsageRepository repository = new AppDataUsageRepository( - requireContext(), - ActivityManager.getCurrentUser(), - mSubscriptionInfoEntity == null ? null : mSubscriptionInfoEntity.carrierId, - appItem -> mUidDetailProvider.getUidDetail(appItem.key, true).packageName - ); - for (var itemPercentPair : repository.getAppPercent(buckets)) { - final AppDataUsagePreference preference = new AppDataUsagePreference(getContext(), - itemPercentPair.getFirst(), itemPercentPair.getSecond(), mUidDetailProvider); - preference.setOnPreferenceClickListener(p -> { - AppDataUsagePreference pref = (AppDataUsagePreference) p; - startAppDataUsage(pref.getItem()); - return true; - }); - mApps.addPreference(preference); - } - } - - @VisibleForTesting - void startAppDataUsage(AppItem item) { - if (mCycleData == null) { - return; - } - final Bundle args = new Bundle(); - args.putParcelable(AppDataUsage.ARG_APP_ITEM, item); - args.putParcelable(AppDataUsage.ARG_NETWORK_TEMPLATE, mTemplate); - if (mCycles == null) { - mCycles = new ArrayList<>(); - for (NetworkCycleChartData data : mCycleData) { - if (mCycles.isEmpty()) { - mCycles.add(data.getEndTime()); - } - mCycles.add(data.getStartTime()); - } - } - args.putSerializable(AppDataUsage.ARG_NETWORK_CYCLES, mCycles); - args.putLong(AppDataUsage.ARG_SELECTED_CYCLE, - mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getEndTime()); - - new SubSettingLauncher(getContext()) - .setDestination(AppDataUsage.class.getName()) - .setTitleRes(R.string.data_usage_app_summary_title) - .setArguments(args) - .setSourceMetricsCategory(getMetricsCategory()) - .launch(); - } - private final OnItemSelectedListener mCycleListener = new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { @@ -502,44 +434,6 @@ public class DataUsageList extends DataUsageBaseFragment } }; - private final LoaderCallbacks mNetworkStatsDetailCallbacks = - new LoaderCallbacks<>() { - @Override - @NonNull - public Loader onCreateLoader(int id, Bundle args) { - return new NetworkStatsSummaryLoader.Builder(getContext()) - .setStartTime(mChart.getInspectStart()) - .setEndTime(mChart.getInspectEnd()) - .setNetworkTemplate(mTemplate) - .build(); - } - - @Override - public void onLoadFinished( - @NonNull Loader loader, NetworkStats data) { - bindStats(AppDataUsageRepository.Companion.convertToBuckets(data)); - updateEmptyVisible(); - } - - @Override - public void onLoaderReset(@NonNull Loader loader) { - mApps.removeAll(); - updateEmptyVisible(); - } - - private void updateEmptyVisible() { - if ((mApps.getPreferenceCount() != 0) - != (getPreferenceScreen().getPreferenceCount() != 0)) { - if (mApps.getPreferenceCount() != 0) { - getPreferenceScreen().addPreference(mUsageAmount); - getPreferenceScreen().addPreference(mApps); - } else { - getPreferenceScreen().removeAll(); - } - } - } - }; - private static boolean isGuestUser(Context context) { if (context == null) return false; final UserManager userManager = context.getSystemService(UserManager.class); diff --git a/src/com/android/settings/datausage/DataUsageListAppsController.kt b/src/com/android/settings/datausage/DataUsageListAppsController.kt new file mode 100644 index 00000000000..cc55e1ad1fc --- /dev/null +++ b/src/com/android/settings/datausage/DataUsageListAppsController.kt @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2023 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.datausage + +import android.app.ActivityManager +import android.content.Context +import android.net.NetworkTemplate +import android.os.Bundle +import androidx.annotation.VisibleForTesting +import androidx.lifecycle.LifecycleCoroutineScope +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.preference.PreferenceGroup +import androidx.preference.PreferenceScreen +import com.android.settings.R +import com.android.settings.core.BasePreferenceController +import com.android.settings.core.SubSettingLauncher +import com.android.settings.datausage.lib.AppDataUsageRepository +import com.android.settingslib.AppItem +import com.android.settingslib.net.NetworkCycleChartData +import com.android.settingslib.net.UidDetailProvider +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class DataUsageListAppsController(context: Context, preferenceKey: String) : + BasePreferenceController(context, preferenceKey) { + + private val uidDetailProvider = UidDetailProvider(context) + private lateinit var template: NetworkTemplate + private lateinit var repository: AppDataUsageRepository + private lateinit var preference: PreferenceGroup + private lateinit var lifecycleScope: LifecycleCoroutineScope + + private var cycleData: List? = null + + fun init(template: NetworkTemplate) { + this.template = template + repository = AppDataUsageRepository( + context = mContext, + currentUserId = ActivityManager.getCurrentUser(), + template = template, + ) { appItem: AppItem -> uidDetailProvider.getUidDetail(appItem.key, true).packageName } + } + + override fun getAvailabilityStatus() = AVAILABLE + + override fun displayPreference(screen: PreferenceScreen) { + super.displayPreference(screen) + preference = screen.findPreference(preferenceKey)!! + } + + override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { + lifecycleScope = viewLifecycleOwner.lifecycleScope + } + + fun setCycleData(cycleData: List?) { + this.cycleData = cycleData + } + + fun update(carrierId: Int?, startTime: Long, endTime: Long) = lifecycleScope.launch { + val apps = withContext(Dispatchers.Default) { + repository.getAppPercent(carrierId, startTime, endTime).map { (appItem, percent) -> + AppDataUsagePreference(mContext, appItem, percent, uidDetailProvider).apply { + setOnPreferenceClickListener { + startAppDataUsage(appItem, endTime) + true + } + } + } + } + preference.removeAll() + for (app in apps) { + preference.addPreference(app) + } + } + + @VisibleForTesting + fun startAppDataUsage(item: AppItem, endTime: Long) { + val cycleData = cycleData ?: return + val args = Bundle().apply { + putParcelable(AppDataUsage.ARG_APP_ITEM, item) + putParcelable(AppDataUsage.ARG_NETWORK_TEMPLATE, template) + val cycles = ArrayList().apply { + for (data in cycleData) { + if (isEmpty()) add(data.endTime) + add(data.startTime) + } + } + putSerializable(AppDataUsage.ARG_NETWORK_CYCLES, cycles) + putLong(AppDataUsage.ARG_SELECTED_CYCLE, endTime) + } + SubSettingLauncher(mContext).apply { + setDestination(AppDataUsage::class.java.name) + setTitleRes(R.string.data_usage_app_summary_title) + setArguments(args) + setSourceMetricsCategory(metricsCategory) + }.launch() + } +} diff --git a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt index 3813af5d200..074a5559edd 100644 --- a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt +++ b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt @@ -17,11 +17,15 @@ package com.android.settings.datausage.lib import android.app.usage.NetworkStats +import android.app.usage.NetworkStatsManager import android.content.Context import android.net.NetworkPolicyManager +import android.net.NetworkTemplate import android.os.Process import android.os.UserHandle +import android.util.Log import android.util.SparseArray +import androidx.annotation.VisibleForTesting import com.android.settings.R import com.android.settingslib.AppItem import com.android.settingslib.net.UidDetailProvider @@ -30,15 +34,18 @@ import com.android.settingslib.spaprivileged.framework.common.userManager class AppDataUsageRepository( private val context: Context, private val currentUserId: Int, - private val carrierId: Int?, - private val getPackageName: (AppItem) -> String, + private val template: NetworkTemplate, + private val getPackageName: (AppItem) -> String?, ) { - data class Bucket( - val uid: Int, - val bytes: Long, - ) + private val networkStatsManager = context.getSystemService(NetworkStatsManager::class.java)!! - fun getAppPercent(buckets: List): List> { + fun getAppPercent(carrierId: Int?, startTime: Long, endTime: Long): List> { + val networkStats = querySummary(startTime, endTime) ?: return emptyList() + return getAppPercent(carrierId, convertToBuckets(networkStats)) + } + + @VisibleForTesting + fun getAppPercent(carrierId: Int?, buckets: List): List> { val items = ArrayList() val knownItems = SparseArray() val profiles = context.userManager.userProfiles @@ -61,7 +68,7 @@ class AppDataUsageRepository( item.restricted = true } - val filteredItems = filterItems(items).sorted() + val filteredItems = filterItems(carrierId, items).sorted() val largest: Long = filteredItems.maxOfOrNull { it.total } ?: 0 return filteredItems.map { item -> val percentTotal = if (largest > 0) (item.total * 100 / largest).toInt() else 0 @@ -69,7 +76,14 @@ class AppDataUsageRepository( } } - private fun filterItems(items: List): List { + private fun querySummary(startTime: Long, endTime: Long): NetworkStats? = try { + networkStatsManager.querySummary(template, startTime, endTime) + } catch (e: RuntimeException) { + Log.e(TAG, "Exception querying network detail.", e) + null + } + + private fun filterItems(carrierId: Int?, items: List): List { // When there is no specified SubscriptionInfo, Wi-Fi data usage will be displayed. // In this case, the carrier service package also needs to be hidden. if (carrierId != null && carrierId !in context.resources.getIntArray( @@ -178,7 +192,15 @@ class AppDataUsageRepository( } companion object { - fun convertToBuckets(stats: NetworkStats): List { + private const val TAG = "AppDataUsageRepository" + + @VisibleForTesting + data class Bucket( + val uid: Int, + val bytes: Long, + ) + + private fun convertToBuckets(stats: NetworkStats): List { val buckets = mutableListOf() stats.use { val bucket = NetworkStats.Bucket() diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java index 4640efea447..b16d336804f 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java @@ -17,7 +17,6 @@ package com.android.settings.datausage; import static com.google.common.truth.Truth.assertThat; - import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -44,19 +43,15 @@ import androidx.loader.app.LoaderManager; import androidx.preference.PreferenceManager; import com.android.settings.R; -import com.android.settings.SettingsActivity; import com.android.settings.network.MobileDataEnabledListener; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.widget.LoadingViewController; -import com.android.settingslib.AppItem; import com.android.settingslib.NetworkPolicyEditor; import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin; -import com.android.settingslib.net.NetworkCycleChartData; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; @@ -67,9 +62,6 @@ import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.util.ReflectionHelpers; -import java.util.ArrayList; -import java.util.List; - @RunWith(RobolectricTestRunner.class) public class DataUsageListTest { @@ -195,34 +187,6 @@ public class DataUsageListTest { assertThat(mDataUsageList.mSubId).isEqualTo(3); } - @Test - public void startAppDataUsage_shouldAddCyclesInfoToLaunchArguments() { - final long startTime = 1521583200000L; - final long endTime = 1521676800000L; - final List data = new ArrayList<>(); - final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder(); - builder.setStartTime(startTime) - .setEndTime(endTime); - data.add(builder.build()); - ReflectionHelpers.setField(mDataUsageList, "mCycleData", data); - final Spinner spinner = mock(Spinner.class); - when(spinner.getSelectedItemPosition()).thenReturn(0); - ReflectionHelpers.setField(mDataUsageList, "mCycleSpinner", spinner); - final ArgumentCaptor intent = ArgumentCaptor.forClass(Intent.class); - - mDataUsageList.startAppDataUsage(new AppItem()); - - verify(mActivity).startActivity(intent.capture()); - final Bundle arguments = - intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS); - assertThat(arguments.getLong(AppDataUsage.ARG_SELECTED_CYCLE)).isEqualTo(endTime); - final ArrayList cycles = - (ArrayList) arguments.getSerializable(AppDataUsage.ARG_NETWORK_CYCLES); - assertThat(cycles).hasSize(2); - assertThat(cycles.get(0)).isEqualTo(endTime); - assertThat(cycles.get(1)).isEqualTo(startTime); - } - @Test public void onViewCreated_shouldHideCycleSpinner() { final View view = new View(mActivity); @@ -255,7 +219,6 @@ public class DataUsageListTest { mDataUsageList.onPause(); verify(mLoaderManager).destroyLoader(DataUsageList.LOADER_CHART_DATA); - verify(mLoaderManager).destroyLoader(DataUsageList.LOADER_SUMMARY); } private View getHeader() { diff --git a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListAppsControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListAppsControllerTest.kt new file mode 100644 index 00000000000..af5dc893013 --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListAppsControllerTest.kt @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 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.datausage + +import android.content.Context +import android.content.Intent +import android.net.NetworkTemplate +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.SettingsActivity +import com.android.settingslib.AppItem +import com.android.settingslib.net.NetworkCycleChartData +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.doNothing +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +@RunWith(AndroidJUnit4::class) +class DataUsageListAppsControllerTest { + + private val context: Context = spy(ApplicationProvider.getApplicationContext()) { + doNothing().whenever(mock).startActivity(any()) + } + + private val controller = DataUsageListAppsController(context, "test_key") + + @Before + fun setUp() { + controller.init(mock()) + val data = NetworkCycleChartData.Builder().apply { + setStartTime(START_TIME) + setEndTime(END_TIME) + }.build() + controller.setCycleData(listOf(data)) + } + + @Test + fun startAppDataUsage_shouldAddCyclesInfoToLaunchArguments() { + controller.startAppDataUsage(AppItem(), END_TIME) + + val intent = argumentCaptor { + verify(context).startActivity(capture()) + }.firstValue + val arguments = intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)!! + assertThat(arguments.getLong(AppDataUsage.ARG_SELECTED_CYCLE)).isEqualTo(END_TIME) + assertThat( + arguments.getSerializable(AppDataUsage.ARG_NETWORK_CYCLES, ArrayList::class.java) + ).containsExactly(END_TIME, START_TIME).inOrder() + } + + private companion object { + const val START_TIME = 1521583200000L + const val END_TIME = 1521676800000L + } +} diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt index 016d6d2e484..531e6e7907c 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt @@ -20,12 +20,13 @@ import android.content.Context import android.content.pm.UserInfo import android.content.res.Resources import android.net.NetworkPolicyManager +import android.net.NetworkTemplate import android.os.UserHandle import android.os.UserManager import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R -import com.android.settings.datausage.lib.AppDataUsageRepository.Bucket +import com.android.settings.datausage.lib.AppDataUsageRepository.Companion.Bucket import com.android.settingslib.AppItem import com.android.settingslib.spaprivileged.framework.common.userManager import com.google.common.truth.Truth.assertThat @@ -72,15 +73,15 @@ class AppDataUsageRepositoryTest { val repository = AppDataUsageRepository( context = context, currentUserId = USER_ID, - carrierId = null, - getPackageName = { "" }, + template = Template, + getPackageName = { null }, ) val buckets = listOf( Bucket(uid = APP_ID_1, bytes = 1), Bucket(uid = APP_ID_2, bytes = 2), ) - val appPercentList = repository.getAppPercent(buckets) + val appPercentList = repository.getAppPercent(null, buckets) assertThat(appPercentList).hasSize(2) appPercentList[0].first.apply { @@ -102,15 +103,15 @@ class AppDataUsageRepositoryTest { val repository = AppDataUsageRepository( context = context, currentUserId = USER_ID, - carrierId = HIDING_CARRIER_ID, - getPackageName = { if (it.key == APP_ID_1) HIDING_PACKAGE_NAME else "" }, + template = Template, + getPackageName = { if (it.key == APP_ID_1) HIDING_PACKAGE_NAME else null }, ) val buckets = listOf( Bucket(uid = APP_ID_1, bytes = 1), Bucket(uid = APP_ID_2, bytes = 2), ) - val appPercentList = repository.getAppPercent(buckets) + val appPercentList = repository.getAppPercent(HIDING_CARRIER_ID, buckets) assertThat(appPercentList).hasSize(1) appPercentList[0].first.apply { @@ -127,5 +128,7 @@ class AppDataUsageRepositoryTest { const val APP_ID_2 = 110002 const val HIDING_CARRIER_ID = 4 const val HIDING_PACKAGE_NAME = "hiding.package.name" + + val Template: NetworkTemplate = mock() } }