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

Commit e19d9076 authored by Oli Lan's avatar Oli Lan
Browse files

Allow Communal Profile to work without HSUM.

This removes the dependency of the Communal Profile on HSUM. The
Communal Profile is no longer started in the HsumBootUserInitializer:
it now has its own initializer.

The Communal Profile will be started when user 0 is unlocked. On an HSUM
device, this occurs during boot (at around the same time that the boot
user is switched to).

Bug: 291756061
Test: build for HSUM and non-HSUM; check CP starts as expected
Change-Id: Id2ee86b0bbb67e573e0ad17e5fd57ab62cd5a13b
parent 3932a331
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -723,6 +723,10 @@ public class UserManagerService extends IUserManager.Stub {
                    user.unlockRealtime = SystemClock.elapsedRealtime();
                }
            }
            if (targetUser.getUserIdentifier() == UserHandle.USER_SYSTEM
                    && UserManager.isCommunalProfileEnabled()) {
                mUms.startCommunalProfile();
            }
        }

        @Override
@@ -828,6 +832,26 @@ public class UserManagerService extends IUserManager.Stub {
        return mLocalService;
    }

    private void startCommunalProfile() {
        final int communalProfileId = getCommunalProfileIdUnchecked();
        if (communalProfileId != UserHandle.USER_NULL) {
            Slogf.d(LOG_TAG, "Starting the Communal Profile");
            boolean started = false;
            try {
                started = ActivityManager.getService().startProfile(communalProfileId);
            } catch (RemoteException e) {
                // Should not happen - same process
                e.rethrowAsRuntimeException();
            }
            if (!started) {
                Slogf.wtf(LOG_TAG,
                        "Failed to start communal profile userId=%d", communalProfileId);
            }
        } else {
            Slogf.w(LOG_TAG, "Cannot start Communal Profile because there isn't one");
        }
    }

    /** Marks all ephemeral users as slated for deletion. **/
    private void markEphemeralUsersForRemoval() {
        synchronized (mUsersLock) {
+86 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server;

import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;

import com.android.server.am.ActivityManagerService;
import com.android.server.pm.UserManagerInternal;
import com.android.server.utils.Slogf;
import com.android.server.utils.TimingsTraceAndSlog;

/**
 * Responsible for creating the communal profile at first boot, if required.
 */
public class CommunalProfileInitializer {

    private static final String TAG = CommunalProfileInitializer.class.getSimpleName();

    private UserManagerInternal mUmi;
    private final ActivityManagerService mAms;

    public CommunalProfileInitializer(ActivityManagerService ams) {
        mUmi = LocalServices.getService(UserManagerInternal.class);
        mAms = ams;
    }

    /**
     * Initialize this object and create the Communal Profile if needed.
     */
    public void init(TimingsTraceAndSlog t) {
        Slogf.i(TAG, "init())");

        t.traceBegin("createCommunalProfileIfNeeded");
        createCommunalProfileIfNeeded();
        t.traceEnd();
    }

    private void createCommunalProfileIfNeeded() {
        final int communalProfile = mUmi.getCommunalProfileId();
        if (communalProfile != UserHandle.USER_NULL) {
            Slogf.d(TAG, "Found existing Communal Profile, userId=%d", communalProfile);
            return;
        }

        Slogf.d(TAG, "Creating a new Communal Profile");
        try {
            // TODO: b/293860614 - Create Communal Profile string name
            final UserInfo newProfile = mUmi.createUserEvenWhenDisallowed(
                    /* name= */ null,
                    UserManager.USER_TYPE_PROFILE_COMMUNAL,
                    /* flags= */ 0, /* disallowedPackages= */ null, /* token= */ null);
            Slogf.i(TAG, "Successfully created Communal Profile, userId=%d", newProfile.id);
        } catch (UserManager.CheckedUserOperationException e) {
            Slogf.wtf(TAG, "Communal Profile creation failed", e);
        }
    }

    static void removeCommunalProfileIfPresent() {
        final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
        final int communalProfile = umi.getCommunalProfileId();
        if (communalProfile == UserHandle.USER_NULL) {
            return;
        }
        Slogf.d(TAG, "Removing existing Communal Profile, userId=%d", communalProfile);
        final boolean removeSucceeded = umi.removeUserEvenWhenDisallowed(communalProfile);
        if (!removeSucceeded) {
            Slogf.e(TAG, "Failed to remove Communal Profile, userId=%d", communalProfile);
        }
    }

}
+3 −72
Original line number Diff line number Diff line
@@ -63,13 +63,11 @@ final class HsumBootUserInitializer {

    /** Whether this device should always have a non-removable MainUser, including at first boot. */
    private final boolean mShouldAlwaysHaveMainUser;
    /** Whether this device should have a communal profile created at first boot. */
    private final boolean mShouldAlwaysHaveCommunalProfile;

    /** Static factory method for creating a {@link HsumBootUserInitializer} instance. */
    public static @Nullable HsumBootUserInitializer createInstance(ActivityManagerService am,
            PackageManagerService pms, ContentResolver contentResolver,
            boolean shouldAlwaysHaveMainUser, boolean shouldAlwaysHaveCommunalProfile) {
            boolean shouldAlwaysHaveMainUser) {

        if (!UserManager.isHeadlessSystemUserMode()) {
            return null;
@@ -77,18 +75,17 @@ final class HsumBootUserInitializer {
        return new HsumBootUserInitializer(
                LocalServices.getService(UserManagerInternal.class),
                am, pms, contentResolver,
                shouldAlwaysHaveMainUser, shouldAlwaysHaveCommunalProfile);
                shouldAlwaysHaveMainUser);
    }

    private HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am,
            PackageManagerService pms, ContentResolver contentResolver,
            boolean shouldAlwaysHaveMainUser, boolean shouldAlwaysHaveCommunalProfile) {
            boolean shouldAlwaysHaveMainUser) {
        mUmi = umi;
        mAms = am;
        mPms = pms;
        mContentResolver = contentResolver;
        mShouldAlwaysHaveMainUser = shouldAlwaysHaveMainUser;
        mShouldAlwaysHaveCommunalProfile = shouldAlwaysHaveCommunalProfile;
    }

    /**
@@ -106,11 +103,6 @@ final class HsumBootUserInitializer {
            createMainUserIfNeeded();
            t.traceEnd();
        }
        if (mShouldAlwaysHaveCommunalProfile) {
            t.traceBegin("createCommunalProfileIfNeeded");
            createCommunalProfileIfNeeded();
            t.traceEnd();
        }
    }

    private void createMainUserIfNeeded() {
@@ -134,25 +126,6 @@ final class HsumBootUserInitializer {
        }
    }

    private void createCommunalProfileIfNeeded() {
        final int communalProfile = mUmi.getCommunalProfileId();
        if (communalProfile != UserHandle.USER_NULL) {
            Slogf.d(TAG, "Found existing Communal Profile, userId=%d", communalProfile);
            return;
        }

        Slogf.d(TAG, "Creating a new Communal Profile");
        try {
            final UserInfo newProfile = mUmi.createUserEvenWhenDisallowed(
                    /* name= */ null,  // TODO: Create Communal Profile string name
                    UserManager.USER_TYPE_PROFILE_COMMUNAL,
                    /* flags= */ 0, /* disallowedPackages= */ null, /* token= */ null);
            Slogf.i(TAG, "Successfully created Communal Profile, userId=%d", newProfile.id);
        } catch (UserManager.CheckedUserOperationException e) {
            Slogf.wtf(TAG, "Communal Profile creation failed", e);
        }
    }

    /**
     * Put the device into the correct user state: unlock the system and switch to the boot user.
     *
@@ -176,48 +149,6 @@ final class HsumBootUserInitializer {
        }
    }

    /**
     * Handles any final initialization once the system is already ready.
     *
     * <p>Should only call after {@link ActivityManagerService#systemReady} is completed.
     */
    public void postSystemReady(TimingsTraceAndSlog t) {
        if (mShouldAlwaysHaveCommunalProfile) {
            startCommunalProfile(t);
        } else {
            // As a safeguard, disabling the Communal Profile configuration (or SystemProperty) will
            // purposefully trigger the removal of the Communal Profile at boot time.
            removeCommunalProfileIfNeeded();
        }
    }

    private void startCommunalProfile(TimingsTraceAndSlog t) {
        final int communalProfileId = mUmi.getCommunalProfileId();
        if (communalProfileId != UserHandle.USER_NULL) {
            Slogf.d(TAG, "Starting the Communal Profile");
            t.traceBegin("startCommunalProfile-" + communalProfileId);
            final boolean started = mAms.startProfile(communalProfileId);
            if (!started) {
                Slogf.wtf(TAG, "Failed to start communal profile userId=%d", communalProfileId);
            }
            t.traceEnd();
        } else {
            Slogf.w(TAG, "Cannot start Communal Profile because there isn't one");
        }
    }

    private void removeCommunalProfileIfNeeded() {
        final int communalProfile = mUmi.getCommunalProfileId();
        if (communalProfile == UserHandle.USER_NULL) {
            return;
        }
        Slogf.d(TAG, "Removing existing Communal Profile, userId=%d", communalProfile);
        final boolean removeSucceeded = mUmi.removeUserEvenWhenDisallowed(communalProfile);
        if (!removeSucceeded) {
            Slogf.e(TAG, "Failed to Communal Profile, userId=%d", communalProfile);
        }
    }

    private void observeDeviceProvisioning() {
        if (isDeviceProvisioned()) {
            return;
+14 −8
Original line number Diff line number Diff line
@@ -2781,14 +2781,26 @@ public final class SystemServer implements Dumpable {
        final HsumBootUserInitializer hsumBootUserInitializer =
                HsumBootUserInitializer.createInstance(
                        mActivityManagerService, mPackageManagerService, mContentResolver,
                        context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin),
                        UserManager.isCommunalProfileEnabled());
                        context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin));
        if (hsumBootUserInitializer != null) {
            t.traceBegin("HsumBootUserInitializer.init");
            hsumBootUserInitializer.init(t);
            t.traceEnd();
        }

        CommunalProfileInitializer communalProfileInitializer = null;
        if (UserManager.isCommunalProfileEnabled()) {
            t.traceBegin("CommunalProfileInitializer.init");
            communalProfileInitializer =
                    new CommunalProfileInitializer(mActivityManagerService);
            communalProfileInitializer.init(t);
            t.traceEnd();
        } else {
            t.traceBegin("CommunalProfileInitializer.removeCommunalProfileIfPresent");
            CommunalProfileInitializer.removeCommunalProfileIfPresent();
            t.traceEnd();
        }

        t.traceBegin("StartBootPhaseSystemServicesReady");
        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY);
        t.traceEnd();
@@ -3207,12 +3219,6 @@ public final class SystemServer implements Dumpable {
            t.traceEnd();
        }, t);

        if (hsumBootUserInitializer != null) {
            t.traceBegin("HsumBootUserInitializer.postSystemReady");
            hsumBootUserInitializer.postSystemReady(t);
            t.traceEnd();
        }

        t.traceBegin("LockSettingsThirdPartyAppsStarted");
        LockSettingsInternal lockSettingsInternal =
            LocalServices.getService(LockSettingsInternal.class);