Merge "Highlight row (instead of ripple) when come from search."
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index a99ba65..7cc5d1a 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -162,13 +162,12 @@
         mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
         mPm = activity.getPackageManager();
 
-        retrieveAppEntry();
-        startListeningToPackageRemove();
-
         if (!ensurePackageInfoAvailable(activity)) {
             return;
         }
 
+        startListeningToPackageRemove();
+
         mForceStopOptionsMenuController =
             new ForceStopOptionsMenuController(activity, this /* parent */, mDpm,
                 mMetricsFeatureProvider, getLifecycle());
@@ -205,6 +204,10 @@
 
     @Override
     protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
+        retrieveAppEntry();
+        if (mPackageInfo == null) {
+            return null;
+        }
         final String packageName = getPackageName();
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final Lifecycle lifecycle = getLifecycle();
@@ -262,9 +265,6 @@
     }
 
     ApplicationsState.AppEntry getAppEntry() {
-        if (mAppEntry == null) {
-            retrieveAppEntry();
-        }
         return mAppEntry;
     }
 
@@ -273,9 +273,6 @@
     }
 
     PackageInfo getPackageInfo() {
-        if (mAppEntry == null) {
-            retrieveAppEntry();
-        }
         return mPackageInfo;
     }
 
@@ -361,7 +358,12 @@
                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
                             .execute((Object) null);
                 }
-                // continue with following operations
+                if (!refreshUi()) {
+                    onPackageRemoved();
+                } else {
+                    startListeningToPackageRemove();
+                }
+                break;
             case REQUEST_REMOVE_DEVICE_ADMIN:
                 if (!refreshUi()) {
                     setIntentAndFinish(true, true);
@@ -622,7 +624,8 @@
         return mPackageName;
     }
 
-    private void retrieveAppEntry() {
+    @VisibleForTesting
+    void retrieveAppEntry() {
         final Activity activity = getActivity();
         if (activity == null) {
             return;
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java
index 070e758..9bcf2a2 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java
@@ -116,7 +116,7 @@
         mConfig.setCardLayout(holder, suggestionCount, position);
         final Icon icon = suggestion.getIcon();
         final Drawable drawable = mCache.getIcon(icon);
-        if (drawable != null && TextUtils.equals(icon.getResPackage(), mContext.getPackageName())) {
+        if ((suggestion.getFlags() & Suggestion.FLAG_ICON_TINTABLE) != 0) {
             drawable.setTint(Utils.getColorAccent(mContext));
         }
         holder.icon.setImageDrawable(drawable);
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index 93f75bf..4eb2ddd 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -58,7 +58,7 @@
 
     @Override
     public boolean isAvailable() {
-        return true;
+        return mTelephonyManager.isVoiceCapable();
     }
 
     @Override
diff --git a/src/com/android/settings/users/UserCapabilities.java b/src/com/android/settings/users/UserCapabilities.java
index 084a5db..f1bfae9 100644
--- a/src/com/android/settings/users/UserCapabilities.java
+++ b/src/com/android/settings/users/UserCapabilities.java
@@ -34,6 +34,7 @@
     boolean mCanAddGuest;
     boolean mDisallowAddUser;
     boolean mDisallowAddUserSetByAdmin;
+    boolean mDisallowSwitchUser;
     RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
 
     private UserCapabilities() {}
@@ -79,6 +80,9 @@
         final boolean canAddUsersWhenLocked = mIsAdmin || Settings.Global.getInt(
                 context.getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1;
         mCanAddGuest = !mIsGuest && !mDisallowAddUser && canAddUsersWhenLocked;
+
+        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mDisallowSwitchUser = userManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
     }
 
     public boolean isAdmin() {
@@ -109,6 +113,7 @@
                 ", mCanAddGuest=" + mCanAddGuest +
                 ", mDisallowAddUser=" + mDisallowAddUser +
                 ", mEnforcedAdmin=" + mEnforcedAdmin +
+                ", mDisallowSwitchUser=" + mDisallowSwitchUser +
                 '}';
     }
 }
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index c8c4c25..f6bacd8 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -757,8 +757,12 @@
                     synchronized (mUserLock) {
                         if (userType == USER_TYPE_USER) {
                             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
-                            mHandler.sendMessage(mHandler.obtainMessage(
-                                    MESSAGE_SETUP_USER, user.id, user.serialNumber));
+                            // Skip setting up user which results in user switching when the
+                            // restriction is set.
+                            if (!mUserCaps.mDisallowSwitchUser) {
+                                mHandler.sendMessage(mHandler.obtainMessage(
+                                        MESSAGE_SETUP_USER, user.id, user.serialNumber));
+                            }
                         } else {
                             mHandler.sendMessage(mHandler.obtainMessage(
                                     MESSAGE_CONFIG_USER, user.id, user.serialNumber));
@@ -845,8 +849,12 @@
                 } else {
                     pref.setSummary(R.string.user_summary_not_set_up);
                 }
-                pref.setOnPreferenceClickListener(this);
-                pref.setSelectable(true);
+                // Disallow setting up user which results in user switching when the restriction is
+                // set.
+                if (!mUserCaps.mDisallowSwitchUser) {
+                    pref.setOnPreferenceClickListener(this);
+                    pref.setSelectable(true);
+                }
             } else if (user.isRestricted()) {
                 pref.setSummary(R.string.user_summary_restricted_profile);
             }
@@ -885,8 +893,13 @@
             pref.setTitle(R.string.user_guest);
             pref.setIcon(getEncircledDefaultIcon());
             userPreferences.add(pref);
-            pref.setDisabledByAdmin(
-                    mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
+            if (mUserCaps.mDisallowAddUser) {
+                pref.setDisabledByAdmin(mUserCaps.mEnforcedAdmin);
+            } else if (mUserCaps.mDisallowSwitchUser) {
+                pref.setDisabledByAdmin(RestrictedLockUtils.getDeviceOwner(context));
+            } else {
+                pref.setDisabledByAdmin(null);
+            }
             int finalGuestId = guestId;
             pref.setOnPreferenceClickListener(preference -> {
                 int id = finalGuestId;
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java
index 87b82ad..fabf9ae 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppInfoDashboardFragmentTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -191,6 +192,22 @@
     }
 
     @Test
+    public void onActivityResult_packageUninstalled_shouldFinishAndRemoveTask() {
+        doReturn(false).when(mFragment).refreshUi();
+
+        mFragment.onActivityResult(mFragment.REQUEST_UNINSTALL, 0, mock(Intent.class));
+
+        verify(mActivity).finishAndRemoveTask();
+    }
+
+    @Test
+    public void getPreferenceControllers_noPackageInfo_shouldReturnNull() {
+        doNothing().when(mFragment).retrieveAppEntry();
+
+        assertThat(mFragment.getPreferenceControllers(mShadowContext)).isNull();
+    }
+
+    @Test
     public void getNumberOfUserWithPackageInstalled_twoUsersInstalled_shouldReturnTwo()
             throws PackageManager.NameNotFoundException{
         final String packageName = "Package1";
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
index ebf3dc7..825aee9 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
@@ -215,11 +215,9 @@
     }
 
     @Test
-    public void onBindViewHolder_differentPackage_shouldNotTintIcon()
-        throws PendingIntent.CanceledException {
+    public void onBindViewHolder_iconNotTintable_shouldNotTintIcon()
+            throws PendingIntent.CanceledException {
         final Icon icon = mock(Icon.class);
-        when(icon.getResPackage()).thenReturn("pkg1");
-        when(mActivity.getPackageName()).thenReturn("pkg2");
         final Suggestion suggestion = new Suggestion.Builder("pkg1")
             .setPendingIntent(mock(PendingIntent.class))
             .setIcon(icon)
@@ -243,15 +241,14 @@
     }
 
     @Test
-    public void onBindViewHolder_samePackage_shouldTintIcon()
-        throws PendingIntent.CanceledException {
+    public void onBindViewHolder_iconTintable_shouldTintIcon()
+            throws PendingIntent.CanceledException {
         final Icon icon = mock(Icon.class);
-        final String packageName = "pkg1";
-        when(icon.getResPackage()).thenReturn(packageName);
-        when(mActivity.getPackageName()).thenReturn(packageName);
-        final Suggestion suggestion = new Suggestion.Builder(packageName)
+        final int FLAG_ICON_TINTABLE = 1 << 1;
+        final Suggestion suggestion = new Suggestion.Builder("pkg1")
             .setPendingIntent(mock(PendingIntent.class))
             .setIcon(icon)
+            .setFlags(FLAG_ICON_TINTABLE)
             .build();
         final List<Suggestion> suggestions = new ArrayList<>();
         suggestions.add(suggestion);
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index f30425b..0b83359 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.deviceinfo;
 
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -74,6 +77,20 @@
     }
 
     @Test
+    public void isAvailable_shouldBeTrueIfCallCapable() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
+    public void isAvailable_shouldBeFalseIfNotCallCapable() {
+        when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
+
+        assertFalse(mController.isAvailable());
+    }
+
+    @Test
     public void displayPreference_multiSim_shouldAddSecondPreference() {
         when(mTelephonyManager.getPhoneCount()).thenReturn(2);
 
diff --git a/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java
new file mode 100644
index 0000000..4228ca0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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.users;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.UserManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UserCapabilitiesTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private UserManager mUserManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+    }
+
+    @Test
+    public void disallowUserSwitchWhenRestrictionIsSet() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
+
+        UserCapabilities userCapabilities = UserCapabilities.create(mContext);
+        userCapabilities.updateAddUserCapabilities(mContext);
+
+        assertThat(userCapabilities.mDisallowSwitchUser).isTrue();
+    }
+
+    @Test
+    public void allowUserSwitchWhenRestrictionIsNotSet() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
+
+        UserCapabilities userCapabilities = UserCapabilities.create(mContext);
+        userCapabilities.updateAddUserCapabilities(mContext);
+
+        assertThat(userCapabilities.mDisallowSwitchUser).isFalse();
+    }
+}