diff --git a/res/xml/accounts_work_dashboard_settings.xml b/res/xml/accounts_work_dashboard_settings.xml index c24ea6f5403..80d6b224f15 100644 --- a/res/xml/accounts_work_dashboard_settings.xml +++ b/res/xml/accounts_work_dashboard_settings.xml @@ -28,6 +28,7 @@ android:persistent="false" android:title="@string/autofill_passwords" settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController" + settings:forWork="true" settings:keywords="@string/autofill_keywords" /> availableServices) { super(context, preferenceKey); mPm = context.getPackageManager(); mIconFactory = IconDrawableFactory.newInstance(mContext); + mServices = new ArrayList<>(); + } + + @OnLifecycleEvent(ON_CREATE) + void onCreate(LifecycleOwner lifecycleOwner) { + init(lifecycleOwner, AutofillServiceInfo.getAvailableServices(mContext, getUser())); + } + + @VisibleForTesting + void init(LifecycleOwner lifecycleOwner, List availableServices) { + mLifecycleOwner = lifecycleOwner; + for (int i = availableServices.size() - 1; i >= 0; i--) { final String passwordsActivity = availableServices.get(i).getPasswordsActivity(); if (TextUtils.isEmpty(passwordsActivity)) { availableServices.remove(i); } } - mServices = availableServices; - } - - @OnLifecycleEvent(ON_CREATE) - void onCreate(LifecycleOwner lifecycleOwner) { - mLifecycleOwner = lifecycleOwner; + // TODO: Reverse the loop above and add to mServices directly. + mServices.clear(); + mServices.addAll(availableServices); } @Override @@ -109,8 +112,7 @@ public class PasswordsPreferenceController extends BasePreferenceController public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); final PreferenceGroup group = screen.findPreference(getPreferenceKey()); - // TODO(b/169455298): Show work profile passwords too. - addPasswordPreferences(screen.getContext(), UserHandle.myUserId(), group); + addPasswordPreferences(screen.getContext(), getUser(), group); } private void addPasswordPreferences( @@ -126,9 +128,15 @@ public class PasswordsPreferenceController extends BasePreferenceController serviceInfo.applicationInfo, user); pref.setIcon(Utils.getSafeIcon(icon)); - pref.setIntent( - new Intent(Intent.ACTION_MAIN) - .setClassName(serviceInfo.packageName, service.getPasswordsActivity())); + pref.setOnPreferenceClickListener(p -> { + final Intent intent = + new Intent(Intent.ACTION_MAIN) + .setClassName( + serviceInfo.packageName, + service.getPasswordsActivity()); + prefContext.startActivityAsUser(intent, UserHandle.of(user)); + return true; + }); // Set an empty summary to avoid a UI flicker when the value loads. pref.setSummary(R.string.summary_placeholder); @@ -213,4 +221,9 @@ public class PasswordsPreferenceController extends BasePreferenceController } } } + + private int getUser() { + UserHandle workUser = getWorkProfileUser(); + return workUser != null ? workUser.getIdentifier() : UserHandle.myUserId(); + } } diff --git a/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java index 25d989385d3..da860ecb539 100644 --- a/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java @@ -21,11 +21,19 @@ import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_U import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.os.Looper; +import android.os.UserHandle; import android.service.autofill.AutofillServiceInfo; import androidx.lifecycle.Lifecycle; @@ -40,9 +48,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.collect.Lists; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import java.util.Collections; import java.util.List; @@ -56,7 +64,7 @@ public class PasswordsPreferenceControllerTest { @Before public void setUp() { - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); if (Looper.myLooper() == null) { Looper.prepare(); // needed to create the preference screen } @@ -66,6 +74,15 @@ public class PasswordsPreferenceControllerTest { mScreen.addPreference(mPasswordsPreferenceCategory); } + @Test + // Tests that getAvailabilityStatus() does not throw an exception if it's called before the + // Controller is initialized (this can happen during indexing). + public void getAvailabilityStatus_withoutInit_returnsUnavailable() { + PasswordsPreferenceController controller = + new PasswordsPreferenceController(mContext, mPasswordsPreferenceCategory.getKey()); + assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + @Test public void getAvailabilityStatus_noServices_returnsUnavailable() { PasswordsPreferenceController controller = @@ -105,21 +122,26 @@ public class PasswordsPreferenceControllerTest { assertThat(mPasswordsPreferenceCategory.getPreferenceCount()).isEqualTo(0); } - @Ignore("TODO: Fix the test to handle the service binding.") @Test @UiThreadTest public void displayPreference_withPasswords_addsPreference() { AutofillServiceInfo service = createServiceWithPasswords(); + service.getServiceInfo().packageName = ""; + service.getServiceInfo().name = ""; PasswordsPreferenceController controller = createControllerWithServices(Lists.newArrayList(service)); - controller.onCreate(() -> mock(Lifecycle.class)); + doReturn(false).when(mContext).bindServiceAsUser(any(), any(), anyInt(), any()); controller.displayPreference(mScreen); assertThat(mPasswordsPreferenceCategory.getPreferenceCount()).isEqualTo(1); Preference pref = mPasswordsPreferenceCategory.getPreference(0); assertThat(pref.getIcon()).isNotNull(); - assertThat(pref.getIntent().getComponent()) + pref.performClick(); + ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); + UserHandle user = mContext.getUser(); + verify(mContext).startActivityAsUser(intentCaptor.capture(), eq(user)); + assertThat(intentCaptor.getValue().getComponent()) .isEqualTo( new ComponentName( service.getServiceInfo().packageName, @@ -128,8 +150,10 @@ public class PasswordsPreferenceControllerTest { private PasswordsPreferenceController createControllerWithServices( List availableServices) { - return new PasswordsPreferenceController( - mContext, mPasswordsPreferenceCategory.getKey(), availableServices); + PasswordsPreferenceController controller = + new PasswordsPreferenceController(mContext, mPasswordsPreferenceCategory.getKey()); + controller.init(() -> mock(Lifecycle.class), availableServices); + return controller; } private AutofillServiceInfo createServiceWithPasswords() {