Loading res/xml/app_data_usage.xml +3 −25 Original line number Diff line number Diff line Loading @@ -24,31 +24,9 @@ android:key="cycle" settings:controller="com.android.settings.datausage.AppDataUsageCycleController" /> <PreferenceCategory android:key="app_data_usage_summary_category"> <Preference android:key="total_usage" android:title="@string/total_size_label" android:selectable="false" android:layout="@layout/horizontal_preference" android:summary="@string/summary_placeholder" /> <Preference android:key="foreground_usage" android:title="@string/data_usage_label_foreground" android:selectable="false" android:layout="@layout/horizontal_preference" android:summary="@string/summary_placeholder" /> <Preference android:key="background_usage" android:title="@string/data_usage_label_background" android:selectable="false" android:layout="@layout/horizontal_preference" android:summary="@string/summary_placeholder" /> </PreferenceCategory> <com.android.settings.spa.preference.ComposePreference android:key="app_data_usage_summary" settings:controller="com.android.settings.datausage.AppDataUsageSummaryController"/> <PreferenceCategory android:key="app_data_usage_settings_category" Loading src/com/android/settings/datausage/AppDataUsage.java +6 −25 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.datausage.lib.AppDataUsageDetailsRepository; import com.android.settings.datausage.lib.NetworkTemplates; import com.android.settings.datausage.lib.NetworkUsageDetailsData; import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager; import com.android.settings.network.SubscriptionUtil; import com.android.settings.widget.EntityHeaderController; Loading @@ -70,17 +69,11 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC static final String ARG_NETWORK_CYCLES = "network_cycles"; static final String ARG_SELECTED_CYCLE = "selected_cycle"; private static final String KEY_TOTAL_USAGE = "total_usage"; private static final String KEY_FOREGROUND_USAGE = "foreground_usage"; private static final String KEY_BACKGROUND_USAGE = "background_usage"; private static final String KEY_RESTRICT_BACKGROUND = "restrict_background"; private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver"; private PackageManager mPackageManager; private final ArraySet<String> mPackages = new ArraySet<>(); private Preference mTotalUsage; private Preference mForegroundUsage; private Preference mBackgroundUsage; private RestrictedSwitchPreference mRestrictBackground; private Drawable mIcon; Loading Loading @@ -139,10 +132,6 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } mTotalUsage = findPreference(KEY_TOTAL_USAGE); mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE); mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE); final List<Integer> uidList = getAppUidList(mAppItem.uids); initCycle(uidList); Loading Loading @@ -255,15 +244,17 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC @VisibleForTesting void initCycle(List<Integer> uidList) { var controller = use(AppDataUsageCycleController.class); var cycleController = use(AppDataUsageCycleController.class); var summaryController = use(AppDataUsageSummaryController.class); var repository = new AppDataUsageDetailsRepository(mContext, mTemplate, mCycles, uidList); controller.init(repository, data -> { bindData(data); cycleController.init(repository, data -> { mIsLoading = false; summaryController.update(data); return Unit.INSTANCE; }); if (mCycles != null) { Log.d(TAG, "setInitialCycles: " + mCycles + " " + mSelectedCycle); controller.setInitialCycles(mCycles, mSelectedCycle); cycleController.setInitialCycles(mCycles, mSelectedCycle); } } Loading Loading @@ -314,16 +305,6 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } @VisibleForTesting void bindData(@NonNull NetworkUsageDetailsData data) { mIsLoading = false; mTotalUsage.setSummary(DataUsageUtils.formatDataUsage(mContext, data.getTotalUsage())); mForegroundUsage.setSummary( DataUsageUtils.formatDataUsage(mContext, data.getForegroundUsage())); mBackgroundUsage.setSummary( DataUsageUtils.formatDataUsage(mContext, data.getBackgroundUsage())); } private boolean getAppRestrictBackground() { final int uid = mAppItem.key; final int uidPolicy = services.mPolicyManager.getUidPolicy(uid); Loading src/com/android/settings/datausage/AppDataUsageSummaryController.kt 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.datausage.lib.NetworkUsageDetailsData import com.android.settings.spa.preference.ComposePreferenceController import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spaprivileged.framework.compose.placeholder import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map class AppDataUsageSummaryController(context: Context, preferenceKey: String) : ComposePreferenceController(context, preferenceKey) { private val dataFlow = MutableStateFlow(NetworkUsageDetailsData.AllZero) private val totalUsageFlow = dataFlow.map { DataUsageUtils.formatDataUsage(mContext, it.totalUsage).toString() } private val foregroundUsageFlow = dataFlow.map { DataUsageUtils.formatDataUsage(mContext, it.foregroundUsage).toString() } private val backgroundUsageFlow = dataFlow.map { DataUsageUtils.formatDataUsage(mContext, it.backgroundUsage).toString() } override fun getAvailabilityStatus() = AVAILABLE fun update(data: NetworkUsageDetailsData) { dataFlow.value = data } @Composable override fun Content() { Column { val totalUsage by totalUsageFlow.collectAsStateWithLifecycle(placeholder()) val foregroundUsage by foregroundUsageFlow.collectAsStateWithLifecycle(placeholder()) val backgroundUsage by backgroundUsageFlow.collectAsStateWithLifecycle(placeholder()) Preference(object : PreferenceModel { override val title = stringResource(R.string.total_size_label) override val summary = { totalUsage } }) Preference(object : PreferenceModel { override val title = stringResource(R.string.data_usage_label_foreground) override val summary = { foregroundUsage } }) Preference(object : PreferenceModel { override val title = stringResource(R.string.data_usage_label_background) override val summary = { backgroundUsage } }) } } } tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java +0 −31 Original line number Diff line number Diff line Loading @@ -42,16 +42,13 @@ import android.os.Bundle; import android.os.Process; import android.telephony.SubscriptionManager; import android.util.ArraySet; import android.util.Range; import androidx.fragment.app.FragmentActivity; import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.applications.AppInfoBase; import com.android.settings.datausage.lib.NetworkUsageDetailsData; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowDataUsageUtils; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; Loading Loading @@ -252,34 +249,6 @@ public class AppDataUsageTest { verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class)); } @Test public void bindData_shouldUpdateUsageSummary() { mFragment = spy(new TestFragment()); final Context context = RuntimeEnvironment.application; ReflectionHelpers.setField(mFragment, "mContext", context); final long backgroundBytes = 1234L; final long foregroundBytes = 5678L; final NetworkUsageDetailsData appUsage = new NetworkUsageDetailsData( new Range<>(1L, 2L), backgroundBytes + foregroundBytes, foregroundBytes, backgroundBytes ); final Preference backgroundPref = mock(Preference.class); ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref); final Preference foregroundPref = mock(Preference.class); ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref); final Preference totalPref = mock(Preference.class); ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref); mFragment.bindData(appUsage); verify(totalPref).setSummary( DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes)); verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes)); verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes)); } @Test @Config(shadows = {ShadowDataUsageUtils.class, ShadowSubscriptionManager.class, ShadowFragment.class}) Loading tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.util.Range import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.datausage.lib.NetworkUsageDetailsData import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class AppDataUsageSummaryControllerTest { @get:Rule val composeTestRule = createComposeRule() private val context: Context = ApplicationProvider.getApplicationContext() private val controller = AppDataUsageSummaryController(context, TEST_KEY) @Test fun summary() { val appUsage = NetworkUsageDetailsData( range = Range(1L, 2L), totalUsage = BACKGROUND_BYTES + FOREGROUND_BYTES, foregroundUsage = FOREGROUND_BYTES, backgroundUsage = BACKGROUND_BYTES, ) controller.update(appUsage) composeTestRule.setContent { controller.Content() } composeTestRule.onNodeWithText("6.75 kB").assertIsDisplayed() composeTestRule.onNodeWithText("5.54 kB").assertIsDisplayed() composeTestRule.onNodeWithText("1.21 kB").assertIsDisplayed() } private companion object { const val TEST_KEY = "test_key" const val BACKGROUND_BYTES = 1234L const val FOREGROUND_BYTES = 5678L } } Loading
res/xml/app_data_usage.xml +3 −25 Original line number Diff line number Diff line Loading @@ -24,31 +24,9 @@ android:key="cycle" settings:controller="com.android.settings.datausage.AppDataUsageCycleController" /> <PreferenceCategory android:key="app_data_usage_summary_category"> <Preference android:key="total_usage" android:title="@string/total_size_label" android:selectable="false" android:layout="@layout/horizontal_preference" android:summary="@string/summary_placeholder" /> <Preference android:key="foreground_usage" android:title="@string/data_usage_label_foreground" android:selectable="false" android:layout="@layout/horizontal_preference" android:summary="@string/summary_placeholder" /> <Preference android:key="background_usage" android:title="@string/data_usage_label_background" android:selectable="false" android:layout="@layout/horizontal_preference" android:summary="@string/summary_placeholder" /> </PreferenceCategory> <com.android.settings.spa.preference.ComposePreference android:key="app_data_usage_summary" settings:controller="com.android.settings.datausage.AppDataUsageSummaryController"/> <PreferenceCategory android:key="app_data_usage_settings_category" Loading
src/com/android/settings/datausage/AppDataUsage.java +6 −25 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.datausage.lib.AppDataUsageDetailsRepository; import com.android.settings.datausage.lib.NetworkTemplates; import com.android.settings.datausage.lib.NetworkUsageDetailsData; import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager; import com.android.settings.network.SubscriptionUtil; import com.android.settings.widget.EntityHeaderController; Loading @@ -70,17 +69,11 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC static final String ARG_NETWORK_CYCLES = "network_cycles"; static final String ARG_SELECTED_CYCLE = "selected_cycle"; private static final String KEY_TOTAL_USAGE = "total_usage"; private static final String KEY_FOREGROUND_USAGE = "foreground_usage"; private static final String KEY_BACKGROUND_USAGE = "background_usage"; private static final String KEY_RESTRICT_BACKGROUND = "restrict_background"; private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver"; private PackageManager mPackageManager; private final ArraySet<String> mPackages = new ArraySet<>(); private Preference mTotalUsage; private Preference mForegroundUsage; private Preference mBackgroundUsage; private RestrictedSwitchPreference mRestrictBackground; private Drawable mIcon; Loading Loading @@ -139,10 +132,6 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } mTotalUsage = findPreference(KEY_TOTAL_USAGE); mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE); mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE); final List<Integer> uidList = getAppUidList(mAppItem.uids); initCycle(uidList); Loading Loading @@ -255,15 +244,17 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC @VisibleForTesting void initCycle(List<Integer> uidList) { var controller = use(AppDataUsageCycleController.class); var cycleController = use(AppDataUsageCycleController.class); var summaryController = use(AppDataUsageSummaryController.class); var repository = new AppDataUsageDetailsRepository(mContext, mTemplate, mCycles, uidList); controller.init(repository, data -> { bindData(data); cycleController.init(repository, data -> { mIsLoading = false; summaryController.update(data); return Unit.INSTANCE; }); if (mCycles != null) { Log.d(TAG, "setInitialCycles: " + mCycles + " " + mSelectedCycle); controller.setInitialCycles(mCycles, mSelectedCycle); cycleController.setInitialCycles(mCycles, mSelectedCycle); } } Loading Loading @@ -314,16 +305,6 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } @VisibleForTesting void bindData(@NonNull NetworkUsageDetailsData data) { mIsLoading = false; mTotalUsage.setSummary(DataUsageUtils.formatDataUsage(mContext, data.getTotalUsage())); mForegroundUsage.setSummary( DataUsageUtils.formatDataUsage(mContext, data.getForegroundUsage())); mBackgroundUsage.setSummary( DataUsageUtils.formatDataUsage(mContext, data.getBackgroundUsage())); } private boolean getAppRestrictBackground() { final int uid = mAppItem.key; final int uidPolicy = services.mPolicyManager.getUidPolicy(uid); Loading
src/com/android/settings/datausage/AppDataUsageSummaryController.kt 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settings.R import com.android.settings.datausage.lib.NetworkUsageDetailsData import com.android.settings.spa.preference.ComposePreferenceController import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spaprivileged.framework.compose.placeholder import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map class AppDataUsageSummaryController(context: Context, preferenceKey: String) : ComposePreferenceController(context, preferenceKey) { private val dataFlow = MutableStateFlow(NetworkUsageDetailsData.AllZero) private val totalUsageFlow = dataFlow.map { DataUsageUtils.formatDataUsage(mContext, it.totalUsage).toString() } private val foregroundUsageFlow = dataFlow.map { DataUsageUtils.formatDataUsage(mContext, it.foregroundUsage).toString() } private val backgroundUsageFlow = dataFlow.map { DataUsageUtils.formatDataUsage(mContext, it.backgroundUsage).toString() } override fun getAvailabilityStatus() = AVAILABLE fun update(data: NetworkUsageDetailsData) { dataFlow.value = data } @Composable override fun Content() { Column { val totalUsage by totalUsageFlow.collectAsStateWithLifecycle(placeholder()) val foregroundUsage by foregroundUsageFlow.collectAsStateWithLifecycle(placeholder()) val backgroundUsage by backgroundUsageFlow.collectAsStateWithLifecycle(placeholder()) Preference(object : PreferenceModel { override val title = stringResource(R.string.total_size_label) override val summary = { totalUsage } }) Preference(object : PreferenceModel { override val title = stringResource(R.string.data_usage_label_foreground) override val summary = { foregroundUsage } }) Preference(object : PreferenceModel { override val title = stringResource(R.string.data_usage_label_background) override val summary = { backgroundUsage } }) } } }
tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java +0 −31 Original line number Diff line number Diff line Loading @@ -42,16 +42,13 @@ import android.os.Bundle; import android.os.Process; import android.telephony.SubscriptionManager; import android.util.ArraySet; import android.util.Range; import androidx.fragment.app.FragmentActivity; import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.applications.AppInfoBase; import com.android.settings.datausage.lib.NetworkUsageDetailsData; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowDataUsageUtils; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; Loading Loading @@ -252,34 +249,6 @@ public class AppDataUsageTest { verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class)); } @Test public void bindData_shouldUpdateUsageSummary() { mFragment = spy(new TestFragment()); final Context context = RuntimeEnvironment.application; ReflectionHelpers.setField(mFragment, "mContext", context); final long backgroundBytes = 1234L; final long foregroundBytes = 5678L; final NetworkUsageDetailsData appUsage = new NetworkUsageDetailsData( new Range<>(1L, 2L), backgroundBytes + foregroundBytes, foregroundBytes, backgroundBytes ); final Preference backgroundPref = mock(Preference.class); ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref); final Preference foregroundPref = mock(Preference.class); ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref); final Preference totalPref = mock(Preference.class); ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref); mFragment.bindData(appUsage); verify(totalPref).setSummary( DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes)); verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes)); verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes)); } @Test @Config(shadows = {ShadowDataUsageUtils.class, ShadowSubscriptionManager.class, ShadowFragment.class}) Loading
tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.util.Range import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.datausage.lib.NetworkUsageDetailsData import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class AppDataUsageSummaryControllerTest { @get:Rule val composeTestRule = createComposeRule() private val context: Context = ApplicationProvider.getApplicationContext() private val controller = AppDataUsageSummaryController(context, TEST_KEY) @Test fun summary() { val appUsage = NetworkUsageDetailsData( range = Range(1L, 2L), totalUsage = BACKGROUND_BYTES + FOREGROUND_BYTES, foregroundUsage = FOREGROUND_BYTES, backgroundUsage = BACKGROUND_BYTES, ) controller.update(appUsage) composeTestRule.setContent { controller.Content() } composeTestRule.onNodeWithText("6.75 kB").assertIsDisplayed() composeTestRule.onNodeWithText("5.54 kB").assertIsDisplayed() composeTestRule.onNodeWithText("1.21 kB").assertIsDisplayed() } private companion object { const val TEST_KEY = "test_key" const val BACKGROUND_BYTES = 1234L const val FOREGROUND_BYTES = 5678L } }