Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 38509086 authored by Hai Zhang's avatar Hai Zhang
Browse files

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
parent d3c02d87
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -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;
    }
+40 −9
Original line number Diff line number Diff line
@@ -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<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(false);

        assertThat(mController.getAvailabilityStatus()).isEqualTo(
                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
    public void updateState_isRoleHolder_shouldSetSummaryToYes() {
        when(mRoleManager.getRoleHolders(eq(TEST_ROLE_NAME))).thenReturn(Collections.singletonList(
+12 −0
Original line number Diff line number Diff line
@@ -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);
    }