Merge "Add device build information in the backup stage" into udc-dev am: 1d818600a4

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/23240826

Change-Id: I3c91272947fa868bb2ae858115bf0af6440b2b97
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/res/layout/preference_external_action_icon.xml b/res/layout/preference_external_action_icon.xml
new file mode 100644
index 0000000..fcec430
--- /dev/null
+++ b/res/layout/preference_external_action_icon.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_chevron_right_24dp"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginHorizontal="8dp" />
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index 334d4e5..0c5c7a0 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -364,7 +364,7 @@
     <bool name="config_show_wifi_hotspot_settings">true</bool>
 
     <!-- Whether Wi-Fi hotspot speed should be shown or not. -->
-    <bool name="config_show_wifi_hotspot_speed">false</bool>
+    <bool name="config_show_wifi_hotspot_speed">true</bool>
 
     <!-- Whether toggle_airplane is available or not. -->
     <bool name="config_show_toggle_airplane">true</bool>
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 938c075..9aee087 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -265,6 +265,12 @@
             updateUdfpsEnrollView(udfpsEnrollView, props.get(0));
             switch (rotation) {
                 case Surface.ROTATION_90:
+                    final View sudContent = layout.findViewById(R.id.sud_layout_content);
+                    if (sudContent != null) {
+                        sudContent.setPadding(sudContent.getPaddingLeft(), 0,
+                                sudContent.getPaddingRight(), sudContent.getPaddingBottom());
+                    }
+
                     final LinearLayout layoutContainer = layout.findViewById(
                             R.id.layout_container);
                     final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 4dc8f1a..578493a 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -33,6 +33,7 @@
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI;
 
+import android.app.PendingIntent;
 import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
@@ -75,6 +76,8 @@
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.settingslib.widget.AdaptiveIcon;
 
+import com.google.common.collect.Iterables;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -152,7 +155,14 @@
         }
         bindIcon(pref, tile, forceRoundedIcon);
 
-        if (tile instanceof ActivityTile) {
+        if (tile.hasPendingIntent()) {
+            // Pending intent cannot be launched within the settings app panel, and will thus always
+            // be executed directly.
+            pref.setOnPreferenceClickListener(preference -> {
+                launchPendingIntentOrSelectProfile(activity, tile, fragment.getMetricsCategory());
+                return true;
+            });
+        } else if (tile instanceof ActivityTile) {
             final int sourceMetricsCategory = fragment.getMetricsCategory();
             final Bundle metadata = tile.getMetaData();
             String clsName = null;
@@ -441,6 +451,33 @@
         preference.setIcon(iconDrawable);
     }
 
+    private void launchPendingIntentOrSelectProfile(FragmentActivity activity, Tile tile,
+            int sourceMetricCategory) {
+        ProfileSelectDialog.updatePendingIntentsIfNeeded(mContext, tile);
+
+        if (tile.pendingIntentMap.isEmpty()) {
+            Log.w(TAG, "Cannot resolve pendingIntent, skipping. " + tile.getIntent());
+            return;
+        }
+
+        mMetricsFeatureProvider.logSettingsTileClick(tile.getKey(mContext), sourceMetricCategory);
+
+        // Launch the pending intent directly if there's only one available.
+        if (tile.pendingIntentMap.size() == 1) {
+            PendingIntent pendingIntent = Iterables.getOnlyElement(tile.pendingIntentMap.values());
+            try {
+                pendingIntent.send();
+            } catch (PendingIntent.CanceledException e) {
+                Log.w(TAG, "Failed executing pendingIntent. " + pendingIntent.getIntent(), e);
+            }
+            return;
+        }
+
+        ProfileSelectDialog.show(activity.getSupportFragmentManager(), tile,
+                sourceMetricCategory, /* onShowListener= */ null,
+                /* onDismissListener= */ null, /* onCancelListener= */ null);
+    }
+
     private void launchIntentOrSelectProfile(FragmentActivity activity, Tile tile, Intent intent,
             int sourceMetricCategory, TopLevelHighlightMixin highlightMixin,
             boolean isDuplicateClick) {
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 6076a25..f8a5d76 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -31,6 +31,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.LifecycleObserver;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
@@ -47,7 +48,6 @@
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.drawer.DashboardCategory;
-import com.android.settingslib.drawer.ProviderTile;
 import com.android.settingslib.drawer.Tile;
 import com.android.settingslib.search.Indexable;
 
@@ -55,6 +55,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -504,6 +505,10 @@
         // Install dashboard tiles and collect pending observers.
         final boolean forceRoundedIcons = shouldForceRoundedIcon();
         final List<DynamicDataObserver> pendingObservers = new ArrayList<>();
+
+        // Move group tiles to the beginning of the list to ensure they are created before the
+        // other tiles.
+        tiles.sort(Comparator.comparingInt(tile -> tile.getType() == Tile.Type.GROUP ? 0 : 1));
         for (Tile tile : tiles) {
             final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
             if (TextUtils.isEmpty(key)) {
@@ -526,7 +531,14 @@
                 observers = mDashboardFeatureProvider.bindPreferenceToTileAndGetObservers(
                         getActivity(), this, forceRoundedIcons, pref, tile, key,
                         mPlaceholderPreferenceController.getOrder());
-                screen.addPreference(pref);
+                if (tile.hasGroupKey() && mDashboardTilePrefKeys.containsKey(tile.getGroupKey())) {
+                    final Preference group = screen.findPreference(tile.getGroupKey());
+                    if (group instanceof PreferenceCategory) {
+                        ((PreferenceCategory) group).addPreference(pref);
+                    }
+                } else {
+                    screen.addPreference(pref);
+                }
                 registerDynamicDataObservers(observers);
                 mDashboardTilePrefKeys.put(key, observers);
             }
@@ -569,11 +581,28 @@
     }
 
     protected Preference createPreference(Tile tile) {
-        return tile instanceof ProviderTile
-                ? new SwitchPreference(getPrefContext())
-                : tile.hasSwitch()
-                        ? new PrimarySwitchPreference(getPrefContext())
-                        : new Preference(getPrefContext());
+        switch (tile.getType()) {
+            case EXTERNAL_ACTION:
+                Preference externalActionPreference = new Preference(getPrefContext());
+                externalActionPreference
+                        .setWidgetLayoutResource(R.layout.preference_external_action_icon);
+                return externalActionPreference;
+            case SWITCH:
+                return new SwitchPreference(getPrefContext());
+            case SWITCH_WITH_ACTION:
+                return new PrimarySwitchPreference(getPrefContext());
+            case GROUP:
+                mMetricsFeatureProvider.action(
+                        mMetricsFeatureProvider.getAttribution(getActivity()),
+                        SettingsEnums.ACTION_SETTINGS_GROUP_TILE_ADDED_TO_SCREEN,
+                        getMetricsCategory(),
+                        tile.getKey(getContext()),
+                        /* value= */ 0);
+                return new PreferenceCategory((getPrefContext()));
+            case ACTION:
+            default:
+                return new Preference(getPrefContext());
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectDialog.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectDialog.java
index ef6ad83..58a51cb 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectDialog.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectDialog.java
@@ -17,6 +17,7 @@
 package com.android.settings.dashboard.profileselector;
 
 import android.app.Dialog;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
@@ -127,13 +128,25 @@
     @Override
     public void onClick(int position) {
         final UserHandle user = mSelectedTile.userHandle.get(position);
-        // Show menu on top level items.
-        final Intent intent = new Intent(mSelectedTile.getIntent());
-        FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
-                .logStartedIntentWithProfile(intent, mSourceMetricCategory,
-                        position == 1 /* isWorkProfile */);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        getActivity().startActivityAsUser(intent, user);
+        if (!mSelectedTile.hasPendingIntent()) {
+            final Intent intent = new Intent(mSelectedTile.getIntent());
+            FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
+                    .logStartedIntentWithProfile(intent, mSourceMetricCategory,
+                            position == 1 /* isWorkProfile */);
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            getActivity().startActivityAsUser(intent, user);
+        } else {
+            PendingIntent pendingIntent = mSelectedTile.pendingIntentMap.get(user);
+            FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
+                    .logSettingsTileClickWithProfile(mSelectedTile.getKey(getContext()),
+                            mSourceMetricCategory,
+                            position == 1 /* isWorkProfile */);
+            try {
+                pendingIntent.send();
+            } catch (PendingIntent.CanceledException e) {
+                Log.w(TAG, "Failed executing pendingIntent. " + pendingIntent.getIntent(), e);
+            }
+        }
         dismiss();
     }
 
@@ -178,4 +191,36 @@
             }
         }
     }
+
+    /**
+     * Checks the userHandle and pendingIntentMap in the provided tile, and remove the invalid
+     * entries if any.
+     */
+    public static void updatePendingIntentsIfNeeded(Context context, Tile tile) {
+        if (tile.userHandle == null || tile.userHandle.size() <= 1
+                || tile.pendingIntentMap.size() <= 1) {
+            return;
+        }
+        for (UserHandle userHandle : List.copyOf(tile.userHandle)) {
+            if (!tile.pendingIntentMap.containsKey(userHandle)) {
+                if (DEBUG) {
+                    Log.d(TAG, "Delete the user without pending intent: "
+                            + userHandle.getIdentifier());
+                }
+                tile.userHandle.remove(userHandle);
+            }
+        }
+
+        final UserManager userManager = UserManager.get(context);
+        for (UserHandle userHandle : List.copyOf(tile.pendingIntentMap.keySet())) {
+            UserInfo userInfo = userManager.getUserInfo(userHandle.getIdentifier());
+            if (userInfo == null || userInfo.isCloneProfile()) {
+                if (DEBUG) {
+                    Log.d(TAG, "Delete the user: " + userHandle.getIdentifier());
+                }
+                tile.userHandle.remove(userHandle);
+                tile.pendingIntentMap.remove(userHandle);
+            }
+        }
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
index 4ba6eae..f7a940f 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
@@ -43,6 +43,7 @@
 import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -57,6 +58,7 @@
 import android.os.UserManager;
 import android.util.Pair;
 
+import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
@@ -200,6 +202,27 @@
     }
 
     @Test
+    public void bindPreference_providerTileWithPendingIntent_shouldBindIntent() {
+        final Preference preference = new SwitchPreference(RuntimeEnvironment.application);
+        Bundle metaData = new Bundle();
+        metaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label);
+        metaData.putInt(META_DATA_PREFERENCE_SUMMARY, R.string.about_settings_summary);
+        metaData.putInt(META_DATA_KEY_ORDER, 10);
+        metaData.putString(META_DATA_PREFERENCE_KEYHINT, KEY);
+        final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, metaData);
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(RuntimeEnvironment.application, 0, new Intent("test"), 0);
+        tile.pendingIntentMap.put(UserHandle.CURRENT, pendingIntent);
+
+        mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
+                preference, tile, "123", Preference.DEFAULT_ORDER);
+
+        assertThat(preference.getFragment()).isNull();
+        assertThat(preference.getOnPreferenceClickListener()).isNotNull();
+        assertThat(preference.getOrder()).isEqualTo(tile.getOrder());
+    }
+
+    @Test
     public void bindPreference_noFragmentMetadata_shouldBindIntent() {
         final Preference preference = new Preference(RuntimeEnvironment.application);
         mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
@@ -631,6 +654,55 @@
     }
 
     @Test
+    public void clickPreference_providerTileWithPendingIntent_singleUser_executesPendingIntent() {
+        final Preference preference = new SwitchPreference(RuntimeEnvironment.application);
+        Bundle metaData = new Bundle();
+        metaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label);
+        metaData.putInt(META_DATA_PREFERENCE_SUMMARY, R.string.about_settings_summary);
+        metaData.putInt(META_DATA_KEY_ORDER, 10);
+        metaData.putString(META_DATA_PREFERENCE_KEYHINT, KEY);
+        final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, metaData);
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(RuntimeEnvironment.application, 0, new Intent("test"), 0);
+        tile.pendingIntentMap.put(UserHandle.CURRENT, pendingIntent);
+
+        mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
+                preference, tile, "123", Preference.DEFAULT_ORDER);
+        preference.performClick();
+
+        Intent nextStartedActivity =
+                Shadows.shadowOf(RuntimeEnvironment.application).peekNextStartedActivity();
+        assertThat(nextStartedActivity).isNotNull();
+        assertThat(nextStartedActivity.getAction()).isEqualTo("test");
+    }
+
+    @Test
+    public void clickPreference_providerTileWithPendingIntent_multiUser_showsProfileDialog() {
+        final Preference preference = new SwitchPreference(RuntimeEnvironment.application);
+        Bundle metaData = new Bundle();
+        metaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label);
+        metaData.putInt(META_DATA_PREFERENCE_SUMMARY, R.string.about_settings_summary);
+        metaData.putInt(META_DATA_KEY_ORDER, 10);
+        metaData.putString(META_DATA_PREFERENCE_KEYHINT, KEY);
+        final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, metaData);
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(RuntimeEnvironment.application, 0, new Intent("test"), 0);
+        tile.pendingIntentMap.put(UserHandle.CURRENT, pendingIntent);
+        tile.pendingIntentMap.put(new UserHandle(10), pendingIntent);
+
+        mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon,
+                preference, tile, "123", Preference.DEFAULT_ORDER);
+        preference.performClick();
+
+        Fragment dialogFragment =
+                mActivity.getSupportFragmentManager().findFragmentByTag("select_profile");
+        assertThat(dialogFragment).isNotNull();
+        Intent nextStartedActivity =
+                Shadows.shadowOf(RuntimeEnvironment.application).peekNextStartedActivity();
+        assertThat(nextStartedActivity).isNull();
+    }
+
+    @Test
     public void openTileIntent_profileSelectionDialog_shouldShow() {
         ShadowUserManager.getShadow().addUser(10, "Someone", 0);
 
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index 0739294..ecaf36f 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -16,7 +16,9 @@
 package com.android.settings.dashboard;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.DASHBOARD_CONTAINER;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -30,6 +32,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.PendingIntent;
 import android.app.settings.SettingsEnums;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -38,15 +41,18 @@
 import android.content.pm.ProviderInfo;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.preference.PreferenceManager.OnActivityResultListener;
 
 import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.slices.BlockingSlicePrefController;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -57,6 +63,7 @@
 import com.android.settingslib.drawer.ActivityTile;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.ProviderTile;
+import com.android.settingslib.drawer.Tile;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -178,6 +185,43 @@
     }
 
     @Test
+    public void displayTilesAsPreference_withGroup_shouldAddTilesIntoGroup() {
+        final ProviderInfo providerInfo = new ProviderInfo();
+        providerInfo.packageName = "pkg";
+        providerInfo.name = "provider";
+        providerInfo.authority = "authority";
+        final Bundle groupTileMetaData = new Bundle();
+        groupTileMetaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_group_key");
+        ProviderTile groupTile = new ProviderTile(providerInfo, mDashboardCategory.key,
+                groupTileMetaData);
+        mDashboardCategory.addTile(groupTile);
+
+        final Bundle subTileMetaData = new Bundle();
+        subTileMetaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key3");
+        subTileMetaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "injected_tile_group_key");
+        subTileMetaData.putParcelable(
+                META_DATA_PREFERENCE_PENDING_INTENT,
+                PendingIntent.getActivity(mContext, 0, new Intent(), 0));
+        ProviderTile subTile = new ProviderTile(providerInfo, mDashboardCategory.key,
+                subTileMetaData);
+        mDashboardCategory.addTile(subTile);
+
+        PreferenceCategory groupPreference = mock(PreferenceCategory.class);
+        when(mFakeFeatureFactory.dashboardFeatureProvider
+                .getTilesForCategory(nullable(String.class)))
+                .thenReturn(mDashboardCategory);
+        when(mFakeFeatureFactory.dashboardFeatureProvider
+                .getDashboardKeyForTile(any(Tile.class)))
+                .then(invocation -> ((Tile) invocation.getArgument(0)).getKey(mContext));
+        when(mTestFragment.mScreen.findPreference("injected_tile_group_key"))
+                .thenReturn(groupPreference);
+        mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
+
+        verify(mTestFragment.mScreen, times(3)).addPreference(nullable(Preference.class));
+        verify(groupPreference).addPreference(nullable(Preference.class));
+    }
+
+    @Test
     public void displayTilesAsPreference_shouldNotAddTilesWithoutIntent() {
         mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
 
@@ -352,6 +396,16 @@
     }
 
     @Test
+    public void createPreference_isActivityTile_returnPreference() {
+        final Preference pref = mTestFragment.createPreference(mActivityTile);
+
+        assertThat(pref).isInstanceOf(Preference.class);
+        assertThat(pref).isNotInstanceOf(PrimarySwitchPreference.class);
+        assertThat(pref).isNotInstanceOf(SwitchPreference.class);
+        assertThat(pref.getWidgetLayoutResource()).isEqualTo(0);
+    }
+
+    @Test
     public void createPreference_isActivityTileAndHasSwitch_returnPrimarySwitchPreference() {
         mActivityTile.getMetaData().putString(META_DATA_PREFERENCE_SWITCH_URI, "uri");
 
@@ -361,6 +415,64 @@
     }
 
     @Test
+    public void createPreference_isProviderTileWithPendingIntent_returnPreferenceWithIcon() {
+        final ProviderInfo providerInfo = new ProviderInfo();
+        providerInfo.packageName = "pkg";
+        providerInfo.name = "provider";
+        providerInfo.authority = "authority";
+        final Bundle metaData = new Bundle();
+        metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key2");
+        ProviderTile providerTile = new ProviderTile(providerInfo, mDashboardCategory.key,
+                metaData);
+        providerTile.pendingIntentMap.put(
+                UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
+
+        final Preference pref = mTestFragment.createPreference(providerTile);
+
+        assertThat(pref).isInstanceOf(Preference.class);
+        assertThat(pref).isNotInstanceOf(PrimarySwitchPreference.class);
+        assertThat(pref).isNotInstanceOf(SwitchPreference.class);
+        assertThat(pref.getWidgetLayoutResource())
+                .isEqualTo(R.layout.preference_external_action_icon);
+    }
+
+    @Test
+    public void createPreference_isProviderTileWithPendingIntentAndSwitch_returnPrimarySwitch() {
+        mProviderTile.pendingIntentMap.put(
+                UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
+
+        final Preference pref = mTestFragment.createPreference(mProviderTile);
+
+        assertThat(pref).isInstanceOf(PrimarySwitchPreference.class);
+    }
+
+    @Test
+    public void createPreference_isGroupTile_returnPreferenceCategory_logTileAdded() {
+        final ProviderInfo providerInfo = new ProviderInfo();
+        providerInfo.packageName = "pkg";
+        providerInfo.name = "provider";
+        providerInfo.authority = "authority";
+        final Bundle metaData = new Bundle();
+        metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key2");
+        ProviderTile providerTile =
+                new ProviderTile(providerInfo, mDashboardCategory.key, metaData);
+        MetricsFeatureProvider metricsFeatureProvider =
+                mFakeFeatureFactory.getMetricsFeatureProvider();
+        when(metricsFeatureProvider.getAttribution(any())).thenReturn(123);
+
+        final Preference pref = mTestFragment.createPreference(providerTile);
+
+        assertThat(pref).isInstanceOf(PreferenceCategory.class);
+        verify(metricsFeatureProvider)
+                .action(
+                        123,
+                        SettingsEnums.ACTION_SETTINGS_GROUP_TILE_ADDED_TO_SCREEN,
+                        mTestFragment.getMetricsCategory(),
+                        "injected_tile_key2",
+                        0);
+    }
+
+    @Test
     public void onActivityResult_test() {
         final int requestCode = 10;
         final int resultCode = 1;
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectDialogTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectDialogTest.java
index 4e81cee..9a13961 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectDialogTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectDialogTest.java
@@ -24,7 +24,9 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Dialog;
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
@@ -119,6 +121,28 @@
     }
 
     @Test
+    public void updatePendingIntentsIfNeeded_removesUsersWithNoPendingIntentsAndCloneProfile() {
+        final UserInfo userInfo = new UserInfo(CLONE_USER.getIdentifier(), "clone_user", null,
+                UserInfo.FLAG_PROFILE, UserManager.USER_TYPE_PROFILE_CLONE);
+        when(mUserManager.getUserInfo(CLONE_USER.getIdentifier())).thenReturn(userInfo);
+        final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
+        tile.userHandle.add(CLONE_USER);
+        tile.userHandle.add(NORMAL_USER);
+        tile.userHandle.add(new UserHandle(10));
+        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        tile.pendingIntentMap.put(CLONE_USER, pendingIntent);
+        tile.pendingIntentMap.put(NORMAL_USER, pendingIntent);
+
+        ProfileSelectDialog.updatePendingIntentsIfNeeded(mContext, tile);
+
+        assertThat(tile.userHandle).hasSize(1);
+        assertThat(tile.userHandle).containsExactly(NORMAL_USER);
+        assertThat(tile.pendingIntentMap).hasSize(1);
+        assertThat(tile.pendingIntentMap).containsKey(NORMAL_USER);
+        verify(mUserManager, times(1)).getUserInfo(CLONE_USER.getIdentifier());
+    }
+
+    @Test
     public void createDialog_showsCorrectTitle() {
         mContext.setTheme(R.style.Theme_AppCompat);