From 38509086712fbda8c3ebb14b41a35b555f1ea938 Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Wed, 23 Jan 2019 16:51:40 -0800 Subject: [PATCH] Show Default app shortcut preference only when app is qualified. This change uses the new isApplicationQualifiedForRole() API on PermissionControllerManager to correctly report availability of default app shortcut preference. Bug: 110557011 Bug: 123238935 Test: atest DefaultAppShortcutPreferenceControllerBaseTest DefaultSmsShortcutPreferenceControllerTest Change-Id: Ib86ab0fd84334a149f7c6c3556297745f2990f47 --- ...ltAppShortcutPreferenceControllerBase.java | 36 +++++++++++++- ...pShortcutPreferenceControllerBaseTest.java | 49 +++++++++++++++---- ...ltSmsShortcutPreferenceControllerTest.java | 12 +++++ 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java b/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java index 804fdbe28d2..20169d8706f 100644 --- a/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java +++ b/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java @@ -20,9 +20,11 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.UserManager; +import android.permission.PermissionControllerManager; import android.text.TextUtils; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.internal.util.CollectionUtils; import com.android.settings.R; @@ -43,6 +45,10 @@ public abstract class DefaultAppShortcutPreferenceControllerBase extends BasePre private final RoleManager mRoleManager; + private boolean mAppQualified; + + private PreferenceScreen mPreferenceScreen; + public DefaultAppShortcutPreferenceControllerBase(Context context, String preferenceKey, String roleName, String packageName) { super(context, preferenceKey); @@ -51,6 +57,17 @@ public abstract class DefaultAppShortcutPreferenceControllerBase extends BasePre mPackageName = packageName; mRoleManager = context.getSystemService(RoleManager.class); + + // TODO: STOPSHIP(b/110557011): Remove this check once we have all default apps migrated. + if (mRoleName != null) { + final PermissionControllerManager permissionControllerManager = + mContext.getSystemService(PermissionControllerManager.class); + permissionControllerManager.isApplicationQualifiedForRole(mRoleName, mPackageName, + mContext.getMainExecutor(), qualified -> { + mAppQualified = qualified; + refreshAvailability(); + }); + } } // TODO: STOPSHIP(b/110557011): Remove this once we have all default apps migrated. @@ -59,6 +76,23 @@ public abstract class DefaultAppShortcutPreferenceControllerBase extends BasePre this(context, preferenceKey, null /* roleName */, packageName); } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + mPreferenceScreen = screen; + } + + private void refreshAvailability() { + if (mPreferenceScreen != null) { + final Preference preference = mPreferenceScreen.findPreference(getPreferenceKey()); + if (preference != null) { + preference.setVisible(isAvailable()); + updateState(preference); + } + } + } + @Override public int getAvailabilityStatus() { if (mContext.getSystemService(UserManager.class).isManagedProfile()) { @@ -104,7 +138,7 @@ public abstract class DefaultAppShortcutPreferenceControllerBase extends BasePre protected boolean hasAppCapability() { // TODO: STOPSHIP(b/110557011): Remove this check once we have all default apps migrated. if (mRoleName != null) { - return mRoleManager.isRoleAvailable(mRoleName); + return mAppQualified; } return false; } diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java index 719b7378cd2..89beede13a5 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java @@ -18,6 +18,7 @@ package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -28,6 +29,7 @@ import android.app.role.RoleManager; import android.content.Context; import android.content.Intent; import android.os.UserManager; +import android.permission.PermissionControllerManager; import androidx.preference.Preference; @@ -38,6 +40,7 @@ import com.android.settings.applications.DefaultAppSettings; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; @@ -48,6 +51,8 @@ import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowUserManager; import java.util.Collections; +import java.util.concurrent.Executor; +import java.util.function.Consumer; @RunWith(RobolectricTestRunner.class) @Config(shadows = ShadowUserManager.class) @@ -60,6 +65,8 @@ public class DefaultAppShortcutPreferenceControllerBaseTest { @Mock private RoleManager mRoleManager; @Mock + private PermissionControllerManager mPermissionControllerManager; + @Mock private Preference mPreference; private Activity mActivity; @@ -71,7 +78,10 @@ public class DefaultAppShortcutPreferenceControllerBaseTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - ShadowApplication.getInstance().setSystemService(Context.ROLE_SERVICE, mRoleManager); + ShadowApplication shadowApplication = ShadowApplication.getInstance(); + shadowApplication.setSystemService(Context.ROLE_SERVICE, mRoleManager); + shadowApplication.setSystemService(Context.PERMISSION_CONTROLLER_SERVICE, + mPermissionControllerManager); mActivity = Robolectric.setupActivity(Activity.class); mShadowUserManager = shadowOf(mActivity.getSystemService(UserManager.class)); mController = new TestRolePreferenceController(mActivity); @@ -79,6 +89,12 @@ public class DefaultAppShortcutPreferenceControllerBaseTest { mLegacyController = new TestLegacyPreferenceController(mActivity); } + @Test + public void constructor_callsIsApplicationQualifiedForRole() { + verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq( + TEST_PACKAGE_NAME), any(Executor.class), any(Consumer.class)); + } + @Test public void getAvailabilityStatus_isManagedProfile_shouldReturnDisabled() { mShadowUserManager.setManagedProfile(true); @@ -88,23 +104,38 @@ public class DefaultAppShortcutPreferenceControllerBaseTest { } @Test - public void getAvailabilityStatus_roleIsAvailable_shouldReturnAvailable() { - mShadowUserManager.setManagedProfile(false); - when(mRoleManager.isRoleAvailable(eq(TEST_ROLE_NAME))).thenReturn(true); - + public void + getAvailabilityStatus_noCallbackForIsApplicationNotQualifiedForRole_shouldReturnUnsupported() { assertThat(mController.getAvailabilityStatus()).isEqualTo( - DefaultAppShortcutPreferenceControllerBase.AVAILABLE); + DefaultAppShortcutPreferenceControllerBase.UNSUPPORTED_ON_DEVICE); } @Test - public void getAvailabilityStatus_roleNotAvailable_shouldReturnDisabled() { - mShadowUserManager.setManagedProfile(false); - when(mRoleManager.isRoleAvailable(eq(TEST_ROLE_NAME))).thenReturn(false); + public void getAvailabilityStatus_applicationIsNotQualifiedForRole_shouldReturnUnsupported() { + final ArgumentCaptor> callbackCaptor = ArgumentCaptor.forClass( + Consumer.class); + verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq( + TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture()); + final Consumer callback = callbackCaptor.getValue(); + callback.accept(false); assertThat(mController.getAvailabilityStatus()).isEqualTo( DefaultAppShortcutPreferenceControllerBase.UNSUPPORTED_ON_DEVICE); } + @Test + public void getAvailabilityStatus_applicationIsQualifiedForRole_shouldReturnAvailable() { + final ArgumentCaptor> callbackCaptor = ArgumentCaptor.forClass( + Consumer.class); + verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq( + TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture()); + final Consumer callback = callbackCaptor.getValue(); + callback.accept(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + DefaultAppShortcutPreferenceControllerBase.AVAILABLE); + } + @Test public void updateState_isRoleHolder_shouldSetSummaryToYes() { when(mRoleManager.getRoleHolders(eq(TEST_ROLE_NAME))).thenReturn(Collections.singletonList( diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java index 6c8435fa29a..b31a10d75dd 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java @@ -18,11 +18,17 @@ package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; +import android.content.Context; +import android.permission.PermissionControllerManager; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.shadows.ShadowApplication; @RunWith(RobolectricTestRunner.class) public class DefaultSmsShortcutPreferenceControllerTest { @@ -30,10 +36,16 @@ public class DefaultSmsShortcutPreferenceControllerTest { private static final String TEST_PACKAGE_NAME = "TestPackage"; private static final String PREFERENCE_KEY = "default_sms_app"; + @Mock + private PermissionControllerManager mPermissionControllerManager; + private DefaultSmsShortcutPreferenceController mController; @Before public void setUp() { + MockitoAnnotations.initMocks(this); + ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE, + mPermissionControllerManager); mController = new DefaultSmsShortcutPreferenceController(RuntimeEnvironment.application, TEST_PACKAGE_NAME); }