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
This commit is contained in:
Hai Zhang
2019-01-23 16:51:40 -08:00
parent d3c02d87f9
commit 3850908671
3 changed files with 87 additions and 10 deletions

View File

@@ -20,9 +20,11 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserManager; import android.os.UserManager;
import android.permission.PermissionControllerManager;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.util.CollectionUtils; import com.android.internal.util.CollectionUtils;
import com.android.settings.R; import com.android.settings.R;
@@ -43,6 +45,10 @@ public abstract class DefaultAppShortcutPreferenceControllerBase extends BasePre
private final RoleManager mRoleManager; private final RoleManager mRoleManager;
private boolean mAppQualified;
private PreferenceScreen mPreferenceScreen;
public DefaultAppShortcutPreferenceControllerBase(Context context, String preferenceKey, public DefaultAppShortcutPreferenceControllerBase(Context context, String preferenceKey,
String roleName, String packageName) { String roleName, String packageName) {
super(context, preferenceKey); super(context, preferenceKey);
@@ -51,6 +57,17 @@ public abstract class DefaultAppShortcutPreferenceControllerBase extends BasePre
mPackageName = packageName; mPackageName = packageName;
mRoleManager = context.getSystemService(RoleManager.class); 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. // 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); 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 @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
if (mContext.getSystemService(UserManager.class).isManagedProfile()) { if (mContext.getSystemService(UserManager.class).isManagedProfile()) {
@@ -104,7 +138,7 @@ public abstract class DefaultAppShortcutPreferenceControllerBase extends BasePre
protected boolean hasAppCapability() { protected boolean hasAppCapability() {
// TODO: STOPSHIP(b/110557011): Remove this check once we have all default apps migrated. // TODO: STOPSHIP(b/110557011): Remove this check once we have all default apps migrated.
if (mRoleName != null) { if (mRoleName != null) {
return mRoleManager.isRoleAvailable(mRoleName); return mAppQualified;
} }
return false; return false;
} }

View File

@@ -18,6 +18,7 @@ package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -28,6 +29,7 @@ import android.app.role.RoleManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.UserManager; import android.os.UserManager;
import android.permission.PermissionControllerManager;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -38,6 +40,7 @@ import com.android.settings.applications.DefaultAppSettings;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric; import org.robolectric.Robolectric;
@@ -48,6 +51,8 @@ import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowUserManager; import org.robolectric.shadows.ShadowUserManager;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowUserManager.class) @Config(shadows = ShadowUserManager.class)
@@ -60,6 +65,8 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
@Mock @Mock
private RoleManager mRoleManager; private RoleManager mRoleManager;
@Mock @Mock
private PermissionControllerManager mPermissionControllerManager;
@Mock
private Preference mPreference; private Preference mPreference;
private Activity mActivity; private Activity mActivity;
@@ -71,7 +78,10 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); 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); mActivity = Robolectric.setupActivity(Activity.class);
mShadowUserManager = shadowOf(mActivity.getSystemService(UserManager.class)); mShadowUserManager = shadowOf(mActivity.getSystemService(UserManager.class));
mController = new TestRolePreferenceController(mActivity); mController = new TestRolePreferenceController(mActivity);
@@ -79,6 +89,12 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
mLegacyController = new TestLegacyPreferenceController(mActivity); 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 @Test
public void getAvailabilityStatus_isManagedProfile_shouldReturnDisabled() { public void getAvailabilityStatus_isManagedProfile_shouldReturnDisabled() {
mShadowUserManager.setManagedProfile(true); mShadowUserManager.setManagedProfile(true);
@@ -88,23 +104,38 @@ public class DefaultAppShortcutPreferenceControllerBaseTest {
} }
@Test @Test
public void getAvailabilityStatus_roleIsAvailable_shouldReturnAvailable() { public void
mShadowUserManager.setManagedProfile(false); getAvailabilityStatus_noCallbackForIsApplicationNotQualifiedForRole_shouldReturnUnsupported() {
when(mRoleManager.isRoleAvailable(eq(TEST_ROLE_NAME))).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo( assertThat(mController.getAvailabilityStatus()).isEqualTo(
DefaultAppShortcutPreferenceControllerBase.AVAILABLE); DefaultAppShortcutPreferenceControllerBase.UNSUPPORTED_ON_DEVICE);
} }
@Test @Test
public void getAvailabilityStatus_roleNotAvailable_shouldReturnDisabled() { public void getAvailabilityStatus_applicationIsNotQualifiedForRole_shouldReturnUnsupported() {
mShadowUserManager.setManagedProfile(false); final ArgumentCaptor<Consumer<Boolean>> callbackCaptor = ArgumentCaptor.forClass(
when(mRoleManager.isRoleAvailable(eq(TEST_ROLE_NAME))).thenReturn(false); Consumer.class);
verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture());
final Consumer<Boolean> callback = callbackCaptor.getValue();
callback.accept(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo( assertThat(mController.getAvailabilityStatus()).isEqualTo(
DefaultAppShortcutPreferenceControllerBase.UNSUPPORTED_ON_DEVICE); DefaultAppShortcutPreferenceControllerBase.UNSUPPORTED_ON_DEVICE);
} }
@Test
public void getAvailabilityStatus_applicationIsQualifiedForRole_shouldReturnAvailable() {
final ArgumentCaptor<Consumer<Boolean>> callbackCaptor = ArgumentCaptor.forClass(
Consumer.class);
verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture());
final Consumer<Boolean> callback = callbackCaptor.getValue();
callback.accept(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
DefaultAppShortcutPreferenceControllerBase.AVAILABLE);
}
@Test @Test
public void updateState_isRoleHolder_shouldSetSummaryToYes() { public void updateState_isRoleHolder_shouldSetSummaryToYes() {
when(mRoleManager.getRoleHolders(eq(TEST_ROLE_NAME))).thenReturn(Collections.singletonList( when(mRoleManager.getRoleHolders(eq(TEST_ROLE_NAME))).thenReturn(Collections.singletonList(

View File

@@ -18,11 +18,17 @@ package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.permission.PermissionControllerManager;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class DefaultSmsShortcutPreferenceControllerTest { public class DefaultSmsShortcutPreferenceControllerTest {
@@ -30,10 +36,16 @@ public class DefaultSmsShortcutPreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "TestPackage"; private static final String TEST_PACKAGE_NAME = "TestPackage";
private static final String PREFERENCE_KEY = "default_sms_app"; private static final String PREFERENCE_KEY = "default_sms_app";
@Mock
private PermissionControllerManager mPermissionControllerManager;
private DefaultSmsShortcutPreferenceController mController; private DefaultSmsShortcutPreferenceController mController;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
mPermissionControllerManager);
mController = new DefaultSmsShortcutPreferenceController(RuntimeEnvironment.application, mController = new DefaultSmsShortcutPreferenceController(RuntimeEnvironment.application,
TEST_PACKAGE_NAME); TEST_PACKAGE_NAME);
} }