Merge "Update Night display icon in Settings" into oc-dr1-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2bbcbc4..774491f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1255,11 +1255,11 @@
     <!-- Title of a dialog shown when the user only has one attempt left to provide the lock before the device, one of its users, or a work profile is wiped. [CHAR LIMIT=NONE] -->
     <string name="lock_last_attempt_before_wipe_warning_title">Your data will be deleted</string>
     <!-- Content of the dialog shown when the user only has one attempt left to provide the device lock pattern before the device is wiped. [CHAR LIMIT=NONE] -->
-    <string name="lock_last_pattern_attempt_before_wipe_device">If you enter an incorrect pattern on the next attempt, this device's data will be deleted</string>
+    <string name="lock_last_pattern_attempt_before_wipe_device">If you enter an incorrect pattern on the next attempt, this device\'s data will be deleted</string>
     <!-- Content of the dialog shown when the user only has one attempt left to provide the device lock PIN before the device is wiped. [CHAR LIMIT=NONE] -->
-    <string name="lock_last_pin_attempt_before_wipe_device">If you enter an incorrect PIN on the next attempt, this device's data will be deleted</string>
+    <string name="lock_last_pin_attempt_before_wipe_device">If you enter an incorrect PIN on the next attempt, this device\'s data will be deleted</string>
     <!-- Content of the dialog shown when the user only has one attempt left to provide the device lock password before the device is wiped. [CHAR LIMIT=NONE] -->
-    <string name="lock_last_password_attempt_before_wipe_device">If you enter an incorrect password on the next attempt, this device's data will be deleted</string>
+    <string name="lock_last_password_attempt_before_wipe_device">If you enter an incorrect password on the next attempt, this device\'s data will be deleted</string>
     <!-- Content of the dialog shown when the user only has one attempt left to provide the user lock pattern before the user is removed. [CHAR LIMIT=NONE] -->
     <string name="lock_last_pattern_attempt_before_wipe_user">If you enter an incorrect pattern on the next attempt, this user will be deleted</string>
     <!-- Content of the dialog shown when the user only has one attempt left to provide the user lock PIN before the user is removed. [CHAR LIMIT=NONE] -->
@@ -1274,7 +1274,7 @@
     <string name="lock_last_password_attempt_before_wipe_profile">If you enter an incorrect password on the next attempt, your work profile and its data will be deleted</string>
 
     <!-- Content of the dialog shown when the user has failed to provide the device lock too many times and the device is wiped. [CHAR LIMIT=NONE] -->
-    <string name="lock_failed_attempts_now_wiping_device">Too many incorrect attempts. This device's data will be deleted.</string>
+    <string name="lock_failed_attempts_now_wiping_device">Too many incorrect attempts. This device\'s data will be deleted.</string>
     <!-- Content of the dialog shown when the user has failed to provide the user lock too many times and the user is removed. [CHAR LIMIT=NONE] -->
     <string name="lock_failed_attempts_now_wiping_user">Too many incorrect attempts. This user will be deleted.</string>
     <!-- Content of the dialog shown when the user has failed to provide the work lock too many times and the work profile is removed. [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
index 26b3427..e668812 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -28,9 +28,9 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SetupWizardUtils;
-import com.android.settings.password.ChooseLockGeneric;
 import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
 import com.android.settings.password.SetupChooseLockGeneric;
+import com.android.settings.password.SetupSkipDialog;
 
 public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
 
@@ -98,9 +98,8 @@
             setResult(RESULT_SKIP);
             finish();
         } else {
-            SetupSkipDialog dialog = SetupSkipDialog.newInstance(
-                    getIntent().getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
-            dialog.show(getFragmentManager());
+            setResult(SetupSkipDialog.RESULT_SKIP);
+            finish();
         }
     }
 
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index d4bc076..b41a40f 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -201,7 +201,7 @@
         private String mFirstPin;
         private RecyclerView mPasswordRestrictionView;
         protected boolean mIsAlphaMode;
-        private Button mCancelButton;
+        protected Button mCancelButton;
         private Button mNextButton;
 
         private TextChangedHandler mTextChangedHandler;
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index 4e73b87..179bd79 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -35,7 +35,6 @@
 import com.android.settings.SetupEncryptionInterstitial;
 import com.android.settings.SetupWizardUtils;
 import com.android.settings.fingerprint.SetupFingerprintEnrollFindSensor;
-import com.android.settings.fingerprint.SetupSkipDialog;
 import com.android.settings.utils.SettingsDividerItemDecoration;
 import com.android.setupwizardlib.GlifPreferenceLayout;
 
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index 0c62c7c..bd935a2 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -84,6 +84,9 @@
         @Override
         public void onViewCreated(View view, Bundle savedInstanceState) {
             super.onViewCreated(view, savedInstanceState);
+
+            mCancelButton.setText(R.string.skip_label);
+
             boolean showOptionsButton = getActivity().getIntent().getBooleanExtra(
                     ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
             if (showOptionsButton) {
@@ -99,6 +102,12 @@
                 case R.id.screen_lock_options:
                     launchChooseLockGeneric();
                     break;
+                case R.id.cancel_button:
+                    SetupSkipDialog dialog = SetupSkipDialog.newInstance(
+                            getActivity().getIntent()
+                                    .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
+                    dialog.show(getFragmentManager());
+                    break;
                 default:
                     super.onClick(v);
             }
diff --git a/src/com/android/settings/fingerprint/SetupSkipDialog.java b/src/com/android/settings/password/SetupSkipDialog.java
similarity index 94%
rename from src/com/android/settings/fingerprint/SetupSkipDialog.java
rename to src/com/android/settings/password/SetupSkipDialog.java
index 842e69c..36646b7 100644
--- a/src/com/android/settings/fingerprint/SetupSkipDialog.java
+++ b/src/com/android/settings/password/SetupSkipDialog.java
@@ -14,12 +14,11 @@
  * limitations under the License
  */
 
-package com.android.settings.fingerprint;
+package com.android.settings.password;
 
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.app.DialogFragment;
 import android.app.FragmentManager;
 import android.content.DialogInterface;
 import android.os.Bundle;
@@ -36,7 +35,7 @@
 
     private static final String ARG_FRP_SUPPORTED = "frp_supported";
     private static final String TAG_SKIP_DIALOG = "skip_dialog";
-    private static final int RESULT_SKIP = Activity.RESULT_FIRST_USER + 10;
+    public static final int RESULT_SKIP = Activity.RESULT_FIRST_USER + 10;
 
     public static SetupSkipDialog newInstance(boolean isFrpSupported) {
         SetupSkipDialog dialog = new SetupSkipDialog();
diff --git a/src/com/android/settings/search/AppSearchResult.java b/src/com/android/settings/search/AppSearchResult.java
index fcb83dc..b59e32e 100644
--- a/src/com/android/settings/search/AppSearchResult.java
+++ b/src/com/android/settings/search/AppSearchResult.java
@@ -18,6 +18,7 @@
 package com.android.settings.search;
 
 import android.content.pm.ApplicationInfo;
+import android.os.UserHandle;
 
 public class AppSearchResult extends SearchResult {
     /**
@@ -30,6 +31,10 @@
         info = builder.mInfo;
     }
 
+    public UserHandle getAppUserHandle() {
+        return new UserHandle(UserHandle.getUserId(info.uid));
+    }
+
     public static class Builder extends SearchResult.Builder {
         protected ApplicationInfo mInfo;
 
diff --git a/src/com/android/settings/search/InstalledAppResultLoader.java b/src/com/android/settings/search/InstalledAppResultLoader.java
index 81b96a1..70a39ee 100644
--- a/src/com/android/settings/search/InstalledAppResultLoader.java
+++ b/src/com/android/settings/search/InstalledAppResultLoader.java
@@ -40,6 +40,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -99,7 +100,7 @@
 
                 final AppSearchResult.Builder builder = new AppSearchResult.Builder();
                 builder.setAppInfo(info)
-                        .setStableId(info.packageName.hashCode())
+                        .setStableId(Objects.hash(info.packageName, user.id))
                         .setTitle(info.loadLabel(pm))
                         .setRank(getRank(wordDiff))
                         .addBreadcrumbs(getBreadCrumb())
diff --git a/src/com/android/settings/search/IntentSearchViewHolder.java b/src/com/android/settings/search/IntentSearchViewHolder.java
index 11adaef..2722d56 100644
--- a/src/com/android/settings/search/IntentSearchViewHolder.java
+++ b/src/com/android/settings/search/IntentSearchViewHolder.java
@@ -16,9 +16,11 @@
  */
 package com.android.settings.search;
 
+import android.content.Intent;
+import android.os.UserHandle;
 import android.view.View;
 
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto;
 
 /**
  * ViewHolder for intent based search results.
@@ -32,7 +34,7 @@
 
     @Override
     public int getClickActionMetricName() {
-        return MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT;
+        return MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT;
     }
 
     @Override
@@ -41,7 +43,15 @@
 
         itemView.setOnClickListener(v -> {
            fragment.onSearchResultClicked(this, result);
-           fragment.startActivity(result.payload.getIntent());
+            final Intent intent = result.payload.getIntent();
+            // Use app user id to support work profile use case.
+            if (result instanceof AppSearchResult) {
+                AppSearchResult appResult = (AppSearchResult) result;
+                UserHandle userHandle = appResult.getAppUserHandle();
+                fragment.getActivity().startActivityAsUser(intent, userHandle);
+            } else {
+                fragment.startActivity(intent);
+            }
         });
     }
 }
diff --git a/src/com/android/settings/search/SearchViewHolder.java b/src/com/android/settings/search/SearchViewHolder.java
index 72fd02320..ed72940 100644
--- a/src/com/android/settings/search/SearchViewHolder.java
+++ b/src/com/android/settings/search/SearchViewHolder.java
@@ -18,8 +18,11 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
 import android.support.v7.widget.RecyclerView;
 import android.text.TextUtils;
+import android.util.IconDrawableFactory;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -46,6 +49,7 @@
 
     protected final MetricsFeatureProvider mMetricsFeatureProvider;
     protected final SearchFeatureProvider mSearchFeatureProvider;
+    private final IconDrawableFactory mIconDrawableFactory;
 
     public SearchViewHolder(View view) {
         super(view);
@@ -59,6 +63,7 @@
         breadcrumbView = view.findViewById(R.id.breadcrumb);
 
         mPlaceholderSummary = view.getContext().getString(R.string.summary_placeholder);
+        mIconDrawableFactory = IconDrawableFactory.newInstance(view.getContext());
     }
 
     public abstract int getClickActionMetricName();
@@ -78,7 +83,12 @@
         if (result instanceof AppSearchResult) {
             AppSearchResult appResult = (AppSearchResult) result;
             PackageManager pm = fragment.getActivity().getPackageManager();
-            iconView.setImageDrawable(appResult.info.loadIcon(pm));
+            UserHandle userHandle = appResult.getAppUserHandle();
+            Drawable badgedIcon =
+                    mIconDrawableFactory.getBadgedIcon(appResult.info, userHandle.getIdentifier());
+            iconView.setImageDrawable(badgedIcon);
+            titleView.setContentDescription(
+                    pm.getUserBadgedLabel(appResult.info.loadLabel(pm), userHandle));
         } else {
             // Valid even when result.icon is null.
             iconView.setImageDrawable(result.icon);
diff --git a/tests/app/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java b/tests/app/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
new file mode 100644
index 0000000..78acc3e
--- /dev/null
+++ b/tests/app/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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.password;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.settings.R;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class SetupChooseLockPasswordAppTest {
+
+    @Rule
+    public ActivityTestRule<SetupChooseLockPassword> mActivityTestRule =
+            new ActivityTestRule<>(
+                    SetupChooseLockPassword.class,
+                    true /* enable touch at launch */,
+                    false /* don't launch at every test */);
+
+    @Test
+    public void testSkipDialogIsShown() throws Throwable {
+        SetupChooseLockPassword activity = mActivityTestRule.launchActivity(null);
+
+        onView(withId(R.id.cancel_button))
+                .check(matches(withText(R.string.skip_label)))
+                .check(matches(isDisplayed()))
+                .perform(click());
+        onView(withId(android.R.id.button1)).check(matches(isDisplayed())).perform(click());
+
+        assertThat(activity.isFinishing()).named("Is finishing").isTrue();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java
new file mode 100644
index 0000000..9ee53ef
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 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.fingerprint;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.app.KeyguardManager;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.password.SetupSkipDialog;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowEventLogWriter;
+import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowKeyguardManager;
+import org.robolectric.util.ActivityController;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+        manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                ShadowEventLogWriter.class,
+                ShadowLockPatternUtils.class,
+                ShadowUserManager.class
+        })
+public class SetupFingerprintEnrollIntroductionTest {
+
+    @Mock
+    private UserInfo mUserInfo;
+
+    private ActivityController<SetupFingerprintEnrollIntroduction> mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        final Intent intent = new Intent();
+        mController = Robolectric.buildActivity(SetupFingerprintEnrollIntroduction.class, intent);
+
+        ShadowUserManager.getShadow().setUserInfo(0, mUserInfo);
+    }
+
+    @Test
+    public void testKeyguardNotSecure_shouldFinishWithSetupSkipDialogResultSkip() {
+        getShadowKeyguardManager().setIsKeyguardSecure(false);
+
+        mController.create().resume();
+
+        final Button skipButton = mController.get().findViewById(R.id.fingerprint_cancel_button);
+        assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE);
+        skipButton.performClick();
+
+        ShadowActivity shadowActivity = Shadows.shadowOf(mController.get());
+        assertThat(mController.get().isFinishing()).named("Is finishing").isTrue();
+        assertThat(shadowActivity.getResultCode()).named("Result code")
+                .isEqualTo(SetupSkipDialog.RESULT_SKIP);
+    }
+
+    @Test
+    public void testKeyguardSecure_shouldFinishWithFingerprintResultSkip() {
+        getShadowKeyguardManager().setIsKeyguardSecure(true);
+
+        mController.create().resume();
+
+        final Button skipButton = mController.get().findViewById(R.id.fingerprint_cancel_button);
+        assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE);
+        skipButton.performClick();
+
+        ShadowActivity shadowActivity = Shadows.shadowOf(mController.get());
+        assertThat(mController.get().isFinishing()).named("Is finishing").isTrue();
+        assertThat(shadowActivity.getResultCode()).named("Result code")
+                .isEqualTo(FingerprintEnrollBase.RESULT_SKIP);
+    }
+
+    private ShadowKeyguardManager getShadowKeyguardManager() {
+        return Shadows.shadowOf(application.getSystemService(KeyguardManager.class));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/search/InstalledAppResultLoaderTest.java b/tests/robotests/src/com/android/settings/search/InstalledAppResultLoaderTest.java
index 645b986..d0a200d 100644
--- a/tests/robotests/src/com/android/settings/search/InstalledAppResultLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/search/InstalledAppResultLoaderTest.java
@@ -22,6 +22,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.os.UserHandle;
 import android.os.UserManager;
 
 import com.android.settings.R;
@@ -47,6 +48,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
 import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
@@ -387,4 +389,41 @@
 
         assertThat(mLoader.loadInBackground().size()).isEqualTo(0);
     }
+
+    @Test
+    public void query_appExistsInBothProfiles() {
+        final String query = "carrot";
+        final String packageName = "carrot";
+        final int user1 = 0;
+        final int user2 = 10;
+        final int uid = 67672;
+        List<UserInfo> infos = new ArrayList<>();
+        infos.add(new UserInfo(user1, "user 1", 0));
+        infos.add(new UserInfo(user2, "user 2", UserInfo.FLAG_MANAGED_PROFILE));
+
+        when(mUserManager.getProfiles(anyInt())).thenReturn(infos);
+
+        when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), eq(user1)))
+                .thenReturn(Arrays.asList(
+                        ApplicationTestUtils.buildInfo(UserHandle.getUid(user1, uid) /* uid */,
+                                packageName, 0 /* flags */,
+                                0 /* targetSdkVersion */)));
+        when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), eq(user2)))
+                .thenReturn(Arrays.asList(
+                        ApplicationTestUtils.buildInfo(UserHandle.getUid(user2, uid) /* uid */,
+                                packageName, 0 /* flags */,
+                                0 /* targetSdkVersion */)));
+
+        mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
+                mSiteMapManager);
+
+        Set<AppSearchResult> searchResults = (Set<AppSearchResult>) mLoader.loadInBackground();
+        assertThat(searchResults).hasSize(2);
+
+        Set<Integer> uidResults = searchResults.stream().map(result -> result.info.uid).collect(
+                Collectors.toSet());
+        assertThat(uidResults).containsExactly(
+                UserHandle.getUid(user1, uid),
+                UserHandle.getUid(user2, uid));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
index 574e4f7..cee3c78 100644
--- a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
+++ b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java
@@ -17,18 +17,30 @@
 
 package com.android.settings.search;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
 import android.view.LayoutInflater;
 import android.view.View;
 
 import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.search.SearchResult.Builder;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -43,25 +55,25 @@
 import java.util.List;
 import java.util.Objects;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class IntentSearchViewHolderTest {
 
     private static final String TITLE = "title";
     private static final String SUMMARY = "summary";
+    private static final int USER_ID = 10;
+    private static final String BADGED_LABEL = "work title";
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
-    @Mock
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private SearchFragment mFragment;
+    @Mock
+    private PackageManager mPackageManager;
     private FakeFeatureFactory mFeatureFactory;
     private IntentSearchViewHolder mHolder;
     private Drawable mIcon;
+    private Drawable mBadgedIcon;
 
     @Before
     public void setUp() {
@@ -74,6 +86,8 @@
         mHolder = new IntentSearchViewHolder(view);
 
         mIcon = context.getDrawable(R.drawable.ic_search_history);
+        mBadgedIcon = context.getDrawable(R.drawable.ic_add);
+        when(mFragment.getActivity().getPackageManager()).thenReturn(mPackageManager);
     }
 
     @Test
@@ -172,6 +186,27 @@
         assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE);
     }
 
+    @Test
+    public void testBindViewElements_appSearchResult() {
+        when(mPackageManager.getUserBadgedLabel(any(CharSequence.class),
+                eq(new UserHandle(USER_ID)))).thenReturn(BADGED_LABEL);
+
+        SearchResult result = getAppSearchResult(
+                TITLE, SUMMARY, mIcon, getApplicationInfo(USER_ID, TITLE, mIcon));
+        mHolder.onBind(mFragment, result);
+        mHolder.itemView.performClick();
+
+        assertThat(mHolder.titleView.getText()).isEqualTo(TITLE);
+        assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY);
+        assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mHolder.titleView.getContentDescription()).isEqualTo(BADGED_LABEL);
+
+        verify(mFragment).onSearchResultClicked(eq(mHolder), any(SearchResult.class));
+        verify(mFragment.getActivity()).startActivityAsUser(
+                any(Intent.class), eq(new UserHandle(USER_ID)));
+    }
+
     private SearchResult getSearchResult(String title, String summary, Drawable icon) {
         Builder builder = new Builder();
         builder.setStableId(Objects.hash(title, summary, icon))
@@ -186,4 +221,26 @@
 
         return builder.build();
     }
+
+    private SearchResult getAppSearchResult(
+            String title, String summary, Drawable icon, ApplicationInfo applicationInfo) {
+        AppSearchResult.Builder builder = new AppSearchResult.Builder();
+        builder.setTitle(title)
+                .setSummary(summary)
+                .setRank(1)
+                .setPayload(new ResultPayload(
+                        new Intent().setComponent(new ComponentName("pkg", "class"))))
+                .addBreadcrumbs(new ArrayList<>())
+                .setIcon(icon);
+        builder.setAppInfo(applicationInfo);
+        return builder.build();
+    }
+
+    private ApplicationInfo getApplicationInfo(int userId, CharSequence appLabel, Drawable icon) {
+        ApplicationInfo applicationInfo = spy(new ApplicationInfo());
+        applicationInfo.uid = UserHandle.getUid(userId, 12345);
+        doReturn(icon).when(applicationInfo).loadIcon(any(PackageManager.class));
+        doReturn(appLabel).when(applicationInfo).loadLabel(any(PackageManager.class));
+        return applicationInfo;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
index b1419ba..7c56dc6 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.testutils.shadow;
 
+import android.app.admin.DevicePolicyManager;
+
 import com.android.internal.widget.LockPatternUtils;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
@@ -27,4 +29,9 @@
     public boolean isSecure(int id) {
         return true;
     }
+
+    @Implementation
+    public int getActivePasswordQuality(int userId) {
+        return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index c67ad36..61346bc 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -16,11 +16,19 @@
 
 package com.android.settings.testutils.shadow;
 
+import android.annotation.UserIdInt;
 import android.content.Context;
+import android.content.pm.UserInfo;
 import android.os.UserManager;
+import android.util.SparseArray;
 
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.internal.ShadowExtractor;
+
+import java.util.Collections;
+import java.util.List;
 
 /**
  * This class provides the API 24 implementation of UserManager.get(Context).
@@ -28,8 +36,34 @@
 @Implements(UserManager.class)
 public class ShadowUserManager {
 
+    private SparseArray<UserInfo> mUserInfos = new SparseArray<>();
+
+    public void setUserInfo(int userHandle, UserInfo userInfo) {
+        mUserInfos.put(userHandle, userInfo);
+    }
+
+    @Implementation
+    public UserInfo getUserInfo(int userHandle) {
+        return mUserInfos.get(userHandle);
+    }
+
+    @Implementation
+    public List<UserInfo> getProfiles(@UserIdInt int userHandle) {
+        return Collections.emptyList();
+    }
+
+    @Implementation
+    public int getCredentialOwnerProfile(@UserIdInt int userHandle) {
+        return userHandle;
+    }
+
     @Implementation
     public static UserManager get(Context context) {
         return (UserManager) context.getSystemService(Context.USER_SERVICE);
     }
+
+    public static ShadowUserManager getShadow() {
+        return (ShadowUserManager) ShadowExtractor.extract(
+                RuntimeEnvironment.application.getSystemService(UserManager.class));
+    }
 }
diff --git a/tests/unit/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/unit/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java
deleted file mode 100644
index 8afed18..0000000
--- a/tests/unit/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2017 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.fingerprint;
-
-
-import static org.mockito.Mockito.doReturn;
-
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.test.ActivityUnitTestCase;
-import android.view.View;
-import android.widget.Button;
-
-import com.android.settings.R;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-public class SetupFingerprintEnrollIntroductionTest
-        extends ActivityUnitTestCase<SetupFingerprintEnrollIntroduction> {
-
-    private TestContext mContext;
-
-    @Mock
-    private KeyguardManager mKeyguardManager;
-
-    private SetupFingerprintEnrollIntroduction mActivity;
-
-    public SetupFingerprintEnrollIntroductionTest() {
-        super(SetupFingerprintEnrollIntroduction.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        MockitoAnnotations.initMocks(this);
-        mContext = new TestContext(getInstrumentation().getTargetContext());
-        setActivityContext(mContext);
-
-        getInstrumentation().runOnMainSync(() -> {
-            final Intent intent = new Intent();
-            mActivity = startActivity(intent,
-                    null /* savedInstanceState */, null /* lastNonConfigurationInstance */);
-        });
-    }
-
-    public void testKeyguardNotSecure_shouldShowSkipDialog() {
-        doReturn(false).when(mKeyguardManager).isKeyguardSecure();
-
-        getInstrumentation().runOnMainSync(() -> {
-            getInstrumentation().callActivityOnCreate(mActivity, null);
-            getInstrumentation().callActivityOnResume(mActivity);
-
-            final Button skipButton =
-                    (Button) mActivity.findViewById(R.id.fingerprint_cancel_button);
-            assertEquals(View.VISIBLE, skipButton.getVisibility());
-            skipButton.performClick();
-        });
-
-        assertFalse(isFinishCalled());
-    }
-
-    public void testKeyguardSecure_shouldNotShowSkipDialog() {
-        doReturn(true).when(mKeyguardManager).isKeyguardSecure();
-
-        getInstrumentation().runOnMainSync(() -> {
-            getInstrumentation().callActivityOnCreate(mActivity, null);
-            getInstrumentation().callActivityOnResume(mActivity);
-
-            final Button skipButton =
-                    (Button) mActivity.findViewById(R.id.fingerprint_cancel_button);
-            assertEquals(View.VISIBLE, skipButton.getVisibility());
-            skipButton.performClick();
-        });
-
-        assertTrue(isFinishCalled());
-    }
-
-    public class TestContext extends ContextWrapper {
-
-        public TestContext(Context base) {
-            super(base);
-        }
-
-        @Override
-        public Object getSystemService(String name) {
-            if (Context.KEYGUARD_SERVICE.equals(name)) {
-                return mKeyguardManager;
-            }
-            return super.getSystemService(name);
-        }
-    }
-}