Merge changes from topic "AppDataUsage" into main

* changes:
  [Expressive design] Update AppDataUsage.
  [Expressive design] Rename ComposeMainSwitchPreference to ComposeGroupSectionPreference.
diff --git a/res/xml/app_data_usage.xml b/res/xml/app_data_usage.xml
index 88f60ef..3135f59 100644
--- a/res/xml/app_data_usage.xml
+++ b/res/xml/app_data_usage.xml
@@ -20,11 +20,15 @@
     android:key="app_data_usage_screen"
     android:title="@string/data_usage_app_summary_title">
 
+    <com.android.settingslib.widget.IntroPreference
+        android:key="app_header"
+        android:order="-10000"/>
+
     <com.android.settings.datausage.SpinnerPreference
         android:key="cycle"
         settings:controller="com.android.settings.datausage.AppDataUsageCycleController" />
 
-    <com.android.settings.spa.preference.ComposePreference
+    <com.android.settings.spa.preference.ComposeGroupSectionPreference
         android:key="app_data_usage_summary"
         settings:controller="com.android.settings.datausage.AppDataUsageSummaryController"/>
 
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index a1a2276..8c948ff 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -18,7 +18,7 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="mobile_network_pref_screen">
 
-    <com.android.settings.spa.preference.ComposeMainSwitchPreference
+    <com.android.settings.spa.preference.ComposeGroupSectionPreference
         android:key="use_sim_switch"
         settings:controller="com.android.settings.network.telephony.MobileNetworkSwitchController"/>
 
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 8480c5c..d8e238c 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -18,6 +18,7 @@
 
 import static com.android.settings.datausage.lib.AppDataUsageRepository.getAppUid;
 import static com.android.settings.datausage.lib.AppDataUsageRepository.getAppUidList;
+import static com.android.settings.spa.app.appinfo.AppInfoSettingsProvider.startAppInfoSettings;
 
 import android.app.Activity;
 import android.app.settings.SettingsEnums;
@@ -45,13 +46,14 @@
 import com.android.settings.datausage.lib.NetworkTemplates;
 import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager;
 import com.android.settings.network.SubscriptionUtil;
-import com.android.settings.widget.EntityHeaderController;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.AppItem;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.net.UidDetail;
 import com.android.settingslib.net.UidDetailProvider;
+import com.android.settingslib.widget.IntroPreference;
 
 import kotlin.Unit;
 
@@ -65,6 +67,8 @@
     private static final String TAG = "AppDataUsage";
 
     static final String ARG_APP_ITEM = "app_item";
+    @VisibleForTesting
+    static final String ARG_APP_HEADER = "app_header";
     static final String ARG_NETWORK_TEMPLATE = "network_template";
     static final String ARG_NETWORK_CYCLES = "network_cycles";
     static final String ARG_SELECTED_CYCLE = "selected_cycle";
@@ -176,7 +180,7 @@
             removePreference(KEY_RESTRICT_BACKGROUND);
         }
 
-        addEntityHeader();
+        setupIntroPreference();
     }
 
     @Override
@@ -320,32 +324,32 @@
     }
 
     @VisibleForTesting
-    void addEntityHeader() {
-        String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
-        int uid = 0;
-        if (pkg != null) {
+    void setupIntroPreference() {
+        final Preference pref = getPreferenceScreen().findPreference(ARG_APP_HEADER);
+        if (pref != null) {
+            pref.setIcon(mIcon);
+            pref.setTitle(mLabel);
+            pref.setSelectable(true);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        if (!(preference instanceof IntroPreference)) return false;
+
+        String pkg = !mPackages.isEmpty() ? mPackages.valueAt(0) : null;
+        if (mAppItem.key > 0 && pkg != null) {
             try {
-                uid = mPackageManager.getPackageUidAsUser(pkg,
+                int uid = mPackageManager.getPackageUidAsUser(pkg,
                         UserHandle.getUserId(mAppItem.key));
+                startAppInfoSettings(pkg, uid, this, 0 /* request */,
+                        FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
+                                .getMetricsCategory(this));
             } catch (PackageManager.NameNotFoundException e) {
                 Log.w(TAG, "Skipping UID because cannot find package " + pkg);
             }
         }
-
-        final boolean showInfoButton = mAppItem.key > 0;
-
-        final Activity activity = getActivity();
-        final Preference pref = EntityHeaderController
-                .newInstance(activity, this, null /* header */)
-                .setUid(uid)
-                .setHasAppInfoLink(showInfoButton)
-                .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
-                        EntityHeaderController.ActionType.ACTION_NONE)
-                .setIcon(mIcon)
-                .setLabel(mLabel)
-                .setPackageName(pkg)
-                .done(getPrefContext());
-        getPreferenceScreen().addPreference(pref);
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/datausage/AppDataUsageSummaryController.kt b/src/com/android/settings/datausage/AppDataUsageSummaryController.kt
index 233e107..fb7101d 100644
--- a/src/com/android/settings/datausage/AppDataUsageSummaryController.kt
+++ b/src/com/android/settings/datausage/AppDataUsageSummaryController.kt
@@ -17,7 +17,6 @@
 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
@@ -28,6 +27,7 @@
 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.spa.widget.ui.Category
 import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.map
@@ -60,7 +60,7 @@
 
     @Composable
     override fun Content() {
-        Column {
+        Category {
             val totalUsage by totalUsageFlow.collectAsStateWithLifecycle(emptyDataUsage)
             val foregroundUsage by foregroundUsageFlow.collectAsStateWithLifecycle(emptyDataUsage)
             val backgroundUsage by backgroundUsageFlow.collectAsStateWithLifecycle(emptyDataUsage)
diff --git a/src/com/android/settings/datausage/SpinnerPreference.java b/src/com/android/settings/datausage/SpinnerPreference.java
index febdead..a1b0f90 100644
--- a/src/com/android/settings/datausage/SpinnerPreference.java
+++ b/src/com/android/settings/datausage/SpinnerPreference.java
@@ -25,8 +25,10 @@
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
+import com.android.settingslib.widget.GroupSectionDividerMixin;
 
-public class SpinnerPreference extends Preference implements CycleAdapter.SpinnerInterface {
+public class SpinnerPreference extends Preference implements CycleAdapter.SpinnerInterface,
+        GroupSectionDividerMixin {
 
     private CycleAdapter mAdapter;
     @Nullable
diff --git a/src/com/android/settings/spa/preference/ComposePreference.kt b/src/com/android/settings/spa/preference/ComposePreference.kt
index 91b2d8a..57aa386 100644
--- a/src/com/android/settings/spa/preference/ComposePreference.kt
+++ b/src/com/android/settings/spa/preference/ComposePreference.kt
@@ -28,7 +28,7 @@
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.widget.GroupSectionDividerMixin
 
-open class ComposeMainSwitchPreference @JvmOverloads constructor(
+open class ComposeGroupSectionPreference @JvmOverloads constructor(
     context: Context,
     attrs: AttributeSet? = null,
     defStyleAttr: Int = 0,
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 4b8c9de..ce33401 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -28,11 +28,13 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -42,6 +44,7 @@
 import android.os.Process;
 import android.telephony.SubscriptionManager;
 import android.util.ArraySet;
+import android.util.FeatureFlagUtils;
 
 import androidx.fragment.app.FragmentActivity;
 import androidx.preference.PreferenceManager;
@@ -51,22 +54,20 @@
 import com.android.settings.applications.AppInfoBase;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
-import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
 import com.android.settings.testutils.shadow.ShadowFragment;
 import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
-import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.AppItem;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.net.UidDetail;
 import com.android.settingslib.net.UidDetailProvider;
+import com.android.settingslib.widget.IntroPreference;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
@@ -79,27 +80,25 @@
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
+@Config(shadows = {ShadowRestrictedLockUtilsInternal.class})
 public class AppDataUsageTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private EntityHeaderController mHeaderController;
     @Mock
     private PackageManager mPackageManager;
 
+    private IntroPreference mIntroPreference;
+
     private AppDataUsage mFragment;
 
+    private Context mContext;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        ShadowEntityHeaderController.setUseMock(mHeaderController);
-        when(mHeaderController.setUid(anyInt())).thenReturn(mHeaderController);
-    }
-
-    @After
-    public void tearDown() {
-        ShadowEntityHeaderController.reset();
+        mContext = spy(RuntimeEnvironment.application);
+        mIntroPreference = new IntroPreference(mContext);
+        FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_ENABLE_SPA, true);
     }
 
     @Test
@@ -161,6 +160,7 @@
     }
 
     @Test
+    @Config(shadows = ShadowFragment.class)
     public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
         mFragment = spy(new TestFragment());
 
@@ -169,12 +169,20 @@
         doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
         ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
 
-        mFragment.addEntityHeader();
+        when(mFragment.getPreferenceScreen().findPreference(AppDataUsage.ARG_APP_HEADER))
+                .thenReturn(mIntroPreference);
+        when(mFragment.getContext()).thenReturn(mContext);
+        doNothing().when(mContext).startActivity(any());
 
-        verify(mHeaderController).setHasAppInfoLink(false);
+        mFragment.setupIntroPreference();
+        mFragment.onPreferenceTreeClick(mIntroPreference);
+
+        verify(mFragment, never()).getActivity();
+        verify(mContext, never()).startActivity(any(Intent.class));
     }
 
     @Test
+    @Config(shadows = ShadowFragment.class)
     public void bindAppHeader_workApp_shouldSetWorkAppUid()
             throws PackageManager.NameNotFoundException {
         final int fakeUserId = 100;
@@ -188,19 +196,21 @@
         ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
         ReflectionHelpers.setField(mFragment, "mPackages", packages);
 
-        when(mPackageManager.getPackageUidAsUser(anyString(), anyInt()))
-                .thenReturn(fakeUserId);
-
-        when(mHeaderController.setHasAppInfoLink(anyBoolean())).thenReturn(mHeaderController);
-
+        when(mPackageManager.getPackageUidAsUser(anyString(), anyInt())).thenReturn(fakeUserId);
         when(mFragment.getPreferenceManager())
                 .thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
         doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
 
-        mFragment.addEntityHeader();
+        when(mFragment.getPreferenceScreen().findPreference(AppDataUsage.ARG_APP_HEADER))
+                .thenReturn(mIntroPreference);
+        when(mFragment.getContext()).thenReturn(mContext);
+        doNothing().when(mContext).startActivity(any());
 
-        verify(mHeaderController).setHasAppInfoLink(true);
-        verify(mHeaderController).setUid(fakeUserId);
+        mFragment.setupIntroPreference();
+        mFragment.onPreferenceTreeClick(mIntroPreference);
+
+        ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).startActivity(argumentCaptor.capture());
     }
 
     @Test