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

Commit 3b658c49 authored by “Ankita's avatar “Ankita
Browse files

Add a new field showInPersonalTab in AppEntry.

Cloned apps should be displayed in the personal tab only and not in new
tab. Hence modify the personal tab filter to include apps whose user
profile has the property set as
UserPropert.SHOW_IN_SETTINGS_WITH_PARENT. Likewise also mofify the work
tab filter to not display these apps.

Bug: 248204976
Test: manual (verfied with primary, clone and managed profile present on
device at the same time)
Test: make RunSettingsLibRoboTests -j40 ROBOTEST_FILTER=ApplicationsStateRoboTest
Test: atest ApplicationsStateTest

Change-Id: I619f2bfe65837e30bfbcdecd43314f735d03b321
parent 54716fa8
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -36,8 +36,10 @@ import android.content.pm.PackageStats;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -1577,8 +1579,8 @@ public class ApplicationsState {
        public long internalSize;
        public long externalSize;
        public String labelDescription;

        public boolean mounted;
        public boolean showInPersonalTab;

        /**
         * Setting this to {@code true} prevents the entry to be filtered by
@@ -1635,6 +1637,33 @@ public class ApplicationsState {
                ThreadUtils.postOnBackgroundThread(
                        () -> this.ensureLabelDescriptionLocked(context));
            }
            this.showInPersonalTab = shouldShowInPersonalTab(context, info.uid);
        }

        /**
         * Checks if the user that the app belongs to have the property
         * {@link UserProperties#SHOW_IN_SETTINGS_WITH_PARENT} set.
         */
        @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
        boolean shouldShowInPersonalTab(Context context, int uid) {
            UserManager userManager = UserManager.get(context);
            int userId = UserHandle.getUserId(uid);

            // Regardless of apk version, if the app belongs to the current user then return true.
            if (userId == ActivityManager.getCurrentUser()) {
                return true;
            }

            // For sdk version < 34, if the app doesn't belong to the current user,
            // then as per earlier behaviour the app shouldn't be displayed in personal tab.
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                return false;
            }

            UserProperties userProperties = userManager.getUserProperties(
                        UserHandle.of(userId));
            return userProperties.getShowInSettings()
                        == UserProperties.SHOW_IN_SETTINGS_WITH_PARENT;
        }

        public void ensureLabel(Context context) {
@@ -1784,7 +1813,7 @@ public class ApplicationsState {

        @Override
        public boolean filterApp(AppEntry entry) {
            return UserHandle.getUserId(entry.info.uid) == mCurrentUser;
            return entry.showInPersonalTab;
        }
    };

@@ -1811,7 +1840,7 @@ public class ApplicationsState {

        @Override
        public boolean filterApp(AppEntry entry) {
            return UserHandle.getUserId(entry.info.uid) != mCurrentUser;
            return !entry.showInPersonalTab;
        }
    };

+11 −0
Original line number Diff line number Diff line
@@ -293,4 +293,15 @@ public class ApplicationsStateTest {

        assertThat(ApplicationsState.FILTER_MOVIES.filterApp(mEntry)).isFalse();
    }

    @Test
    public void testPersonalAndWorkFiltersDisplaysCorrectApps() {
        mEntry.showInPersonalTab = true;
        assertThat(ApplicationsState.FILTER_PERSONAL.filterApp(mEntry)).isTrue();
        assertThat(ApplicationsState.FILTER_WORK.filterApp(mEntry)).isFalse();

        mEntry.showInPersonalTab = false;
        assertThat(ApplicationsState.FILTER_PERSONAL.filterApp(mEntry)).isFalse();
        assertThat(ApplicationsState.FILTER_WORK.filterApp(mEntry)).isTrue();
    }
}
+61 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.settingslib.applications;

import static android.os.UserHandle.MU_ENABLED;
import static android.os.UserHandle.USER_SYSTEM;

import static com.google.common.truth.Truth.assertThat;

@@ -48,9 +49,11 @@ import android.content.pm.ModuleInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.UserProperties;
import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -58,6 +61,8 @@ import android.os.UserManager;
import android.text.TextUtils;
import android.util.IconDrawableFactory;

import androidx.test.core.app.ApplicationProvider;

import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.Callbacks;
import com.android.settingslib.applications.ApplicationsState.Session;
@@ -71,6 +76,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -79,6 +85,7 @@ import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowContextImpl;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.util.ReflectionHelpers;

import java.util.ArrayList;
import java.util.Arrays;
@@ -95,6 +102,7 @@ public class ApplicationsStateRoboTest {
    private final static String LAUNCHABLE_PACKAGE_NAME = "com.android.launchable";

    private static final int PROFILE_USERID = 10;
    private static final int PROFILE_USERID2 = 11;

    private static final String PKG_1 = "PKG1";
    private static final int OWNER_UID_1 = 1001;
@@ -106,6 +114,10 @@ public class ApplicationsStateRoboTest {

    private static final String PKG_3 = "PKG3";
    private static final int OWNER_UID_3 = 1003;
    private static final int PROFILE_UID_3 = UserHandle.getUid(PROFILE_USERID2, OWNER_UID_3);

    private static final String CLONE_USER = "clone_user";
    private static final String RANDOM_USER = "random_user";

    /** Class under test */
    private ApplicationsState mApplicationsState;
@@ -113,6 +125,8 @@ public class ApplicationsStateRoboTest {

    private Application mApplication;

    @Spy
    Context mContext = ApplicationProvider.getApplicationContext();
    @Mock
    private Callbacks mCallbacks;
    @Captor
@@ -738,4 +752,51 @@ public class ApplicationsStateRoboTest {
        when(configChanges.applyNewConfig(any(Resources.class))).thenReturn(false);
        mApplicationsState.setInterestingConfigChanges(configChanges);
    }

    @Test
    public void shouldShowInPersonalTab_forCurrentUser_returnsTrue() {
        ApplicationInfo appInfo = createApplicationInfo(PKG_1);
        AppEntry primaryUserApp = createAppEntry(appInfo, 1);

        assertThat(primaryUserApp.shouldShowInPersonalTab(mContext, appInfo.uid)).isTrue();
    }

    @Test
    public void shouldShowInPersonalTab_userProfilePreU_returnsFalse() {
        ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT",
                Build.VERSION_CODES.TIRAMISU);
        // Create an app (and subsequent AppEntry) in a non-primary user profile.
        ApplicationInfo appInfo1 = createApplicationInfo(PKG_1, PROFILE_UID_1);
        AppEntry nonPrimaryUserApp = createAppEntry(appInfo1, 1);

        assertThat(nonPrimaryUserApp.shouldShowInPersonalTab(mContext, appInfo1.uid)).isFalse();
    }

    @Test
    public void shouldShowInPersonalTab_currentUserIsParent_returnsAsPerUserPropertyOfProfile1() {
        // Mark system user as parent for both profile users.
        ShadowUserManager shadowUserManager = Shadow
                .extract(RuntimeEnvironment.application.getSystemService(UserManager.class));
        shadowUserManager.addProfile(USER_SYSTEM, PROFILE_USERID,
                CLONE_USER, 0);
        shadowUserManager.addProfile(USER_SYSTEM, PROFILE_USERID2,
                RANDOM_USER, 0);
        shadowUserManager.setupUserProperty(PROFILE_USERID,
                /*showInSettings*/ UserProperties.SHOW_IN_SETTINGS_WITH_PARENT);
        shadowUserManager.setupUserProperty(PROFILE_USERID2,
                /*showInSettings*/ UserProperties.SHOW_IN_SETTINGS_NO);

        ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT",
                Build.VERSION_CODES.UPSIDE_DOWN_CAKE);

        // Treat PROFILE_USERID as a clone user profile and create an app PKG_1 in it.
        ApplicationInfo appInfo1 = createApplicationInfo(PKG_1, PROFILE_UID_1);
        // Treat PROFILE_USERID2 as a random non-primary profile and create an app PKG_3 in it.
        ApplicationInfo appInfo2 = createApplicationInfo(PKG_3, PROFILE_UID_3);
        AppEntry nonPrimaryUserApp1 = createAppEntry(appInfo1, 1);
        AppEntry nonPrimaryUserApp2 = createAppEntry(appInfo2, 2);

        assertThat(nonPrimaryUserApp1.shouldShowInPersonalTab(mContext, appInfo1.uid)).isTrue();
        assertThat(nonPrimaryUserApp2.shouldShowInPersonalTab(mContext, appInfo2.uid)).isFalse();
    }
}