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

Commit 2f87ca16 authored by Christine Franks's avatar Christine Franks Committed by Android (Google) Code Review
Browse files

Merge "Support demo mode and demo users" into oc-dr1-dev

parents b02cbdee 361b825c
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -5981,6 +5981,13 @@ public class DevicePolicyManager {
     */
    public static final int MAKE_USER_EPHEMERAL = 0x0002;

    /**
     * Flag used by {@link #createAndManageUser} to specify that the user should be created as a
     * demo user.
     * @hide
     */
    public static final int MAKE_USER_DEMO = 0x0004;

    /**
     * Called by a device owner to create a user with the specified name and a given component of
     * the calling package as profile owner. The UserHandle returned by this method should not be
+29 −7
Original line number Diff line number Diff line
@@ -526,7 +526,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
        Set<String> mOwnerInstalledCaCerts = new ArraySet<>();

        // Used for initialization of users created by createAndManageUsers.
        // Used for initialization of users created by createAndManageUser.
        boolean mAdminBroadcastPending = false;
        PersistableBundle mInitBundle = null;

@@ -4255,6 +4255,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            mInjector.binderRestoreCallingIdentity(token);
        }
    }

    @Override
    public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException {
        final int callingUid = mInjector.binderGetCallingUid();
@@ -7375,9 +7376,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

    private void enableIfNecessary(String packageName, int userId) {
        try {
            ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName,
                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
                    userId);
            final ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName,
                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, userId);
            if (ai.enabledSetting
                    == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
                mIPackageManager.setApplicationEnabledSetting(packageName,
@@ -8131,8 +8131,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if (!mInjector.binderGetCallingUserHandle().isSystem()) {
            throw new SecurityException("createAndManageUser was called from non-system user");
        }
        if (!mInjector.userManagerIsSplitSystemUser()
                && (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0) {
        final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0;
        final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0
                && UserManager.isDeviceInDemoMode(mContext);
        if (ephemeral && !mInjector.userManagerIsSplitSystemUser() && !demo) {
            throw new IllegalArgumentException(
                    "Ephemeral users are only supported on systems with a split system user.");
        }
@@ -8144,9 +8146,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            final long id = mInjector.binderClearCallingIdentity();
            try {
                int userInfoFlags = 0;
                if ((flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0) {
                if (ephemeral) {
                    userInfoFlags |= UserInfo.FLAG_EPHEMERAL;
                }
                if (demo) {
                    userInfoFlags |= UserInfo.FLAG_DEMO;
                }
                UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name,
                        userInfoFlags);
                if (userInfo != null) {
@@ -8178,6 +8183,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                return null;
            }

            final UserInfo userInfo = getUserInfo(userHandle);
            if (userInfo != null && userInfo.isDemo()) {
                try {
                    final ApplicationInfo ai = mIPackageManager.getApplicationInfo(adminPkg,
                            PackageManager.MATCH_DISABLED_COMPONENTS, userHandle);
                    final boolean isSystemApp =
                            ai != null && (ai.flags & (ApplicationInfo.FLAG_SYSTEM
                                    | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
                    if (isSystemApp) {
                        mIPackageManager.setApplicationEnabledSetting(adminPkg,
                                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                                PackageManager.DONT_KILL_APP, userHandle, "DevicePolicyManager");
                    }
                } catch (RemoteException e) {
                }
            }

            setActiveAdmin(profileOwner, true, userHandle);
            // User is not started yet, the broadcast by setActiveAdmin will not be received.
            // So we store adminExtras for broadcasting when the user starts for first time.
+71 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.nullable;
import static org.mockito.Mockito.reset;
@@ -53,6 +54,7 @@ import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.PasswordMetrics;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -338,7 +340,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        // Next, add one more admin.
        // Before doing so, update the application info, now it's enabled.
        setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);

        dpm.setActiveAdmin(admin2, /* replace =*/ false);

@@ -380,6 +382,74 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
    }

    public void testCreateAndManageUser_demoUserSystemApp() throws Exception {
        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);

        setDeviceOwner();

        final int id = UserHandle.getUserId(DpmMockContext.CALLER_UID);

        final UserInfo demoUserInfo = mock(UserInfo.class);
        demoUserInfo.id = id;
        doReturn(UserHandle.of(id)).when(demoUserInfo).getUserHandle();
        doReturn(true).when(demoUserInfo).isDemo();
        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        doReturn(demoUserInfo).when(um).getUserInfo(id);
        doReturn(demoUserInfo).when(mContext.getUserManagerInternal())
                .createUserEvenWhenDisallowed(anyString(), anyInt());

        final ApplicationInfo applicationInfo = getServices().ipackageManager.getApplicationInfo(
                admin2.getPackageName(), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, id);
        applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
        doReturn(applicationInfo).when(getServices().ipackageManager).getApplicationInfo(
                anyString(), anyInt(), anyInt());

        final UserHandle userHandle = dpm.createAndManageUser(admin1, "", admin2, null, 0);

        verify(getServices().ipackageManager, times(1)).setApplicationEnabledSetting(
                eq(admin2.getPackageName()),
                eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
                eq(PackageManager.DONT_KILL_APP),
                eq(id),
                anyString());

        assertNotNull(userHandle);
    }

    public void testCreateAndManageUser_demoUserSystemUpdatedApp() throws Exception {
        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);

        setDeviceOwner();

        final int id = UserHandle.getUserId(DpmMockContext.CALLER_UID);

        final UserInfo demoUserInfo = mock(UserInfo.class);
        demoUserInfo.id = id;
        doReturn(UserHandle.of(id)).when(demoUserInfo).getUserHandle();
        doReturn(true).when(demoUserInfo).isDemo();
        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        doReturn(demoUserInfo).when(um).getUserInfo(id);
        doReturn(demoUserInfo).when(mContext.getUserManagerInternal())
                .createUserEvenWhenDisallowed(anyString(), anyInt());

        final ApplicationInfo applicationInfo = getServices().ipackageManager.getApplicationInfo(
                admin2.getPackageName(), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, id);
        applicationInfo.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
        doReturn(applicationInfo).when(getServices().ipackageManager).getApplicationInfo(
                anyString(), anyInt(), anyInt());

        final UserHandle userHandle = dpm.createAndManageUser(admin1, "", admin2, null, 0);

        verify(getServices().ipackageManager, times(1)).setApplicationEnabledSetting(
                eq(admin2.getPackageName()),
                eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
                eq(PackageManager.DONT_KILL_APP),
                eq(id),
                anyString());

        assertNotNull(userHandle);
    }

    public void testSetActiveAdmin_multiUsers() throws Exception {

        final int ANOTHER_USER_ID = 100;
+5 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.test.mock.MockContext;
import android.util.ArrayMap;

@@ -196,6 +197,10 @@ public class DpmMockContext extends MockContext {
        return mMockSystemServices.packageManager;
    }

    public UserManagerInternal getUserManagerInternal() {
        return mMockSystemServices.userManagerInternal;
    }

    @Override
    public void enforceCallingOrSelfPermission(String permission, String message) {
        if (UserHandle.isSameApp(binder.getCallingUid(), SYSTEM_UID)) {