diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 108350a2b9ce1..0881c9cb2208a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3645,6 +3645,12 @@ public abstract class Context { */ public static final String SYSTEM_HEALTH_SERVICE = "systemhealth"; + /** + * Gatekeeper Service. + * @hide + */ + public static final String GATEKEEPER_SERVICE = "android.service.gatekeeper.IGateKeeperService"; + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index f6e8940db4087..d8be2b6dcc4c4 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -240,6 +240,22 @@ public class Environment { return new File(getDataDirectory(), "system"); } + /** + * Returns the base directory for per-user system directory, device encrypted. + * {@hide} + */ + public static File getDataSystemDeDirectory() { + return buildPath(getDataDirectory(), "system_de"); + } + + /** + * Returns the base directory for per-user system directory, credential encrypted. + * {@hide} + */ + public static File getDataSystemCeDirectory() { + return buildPath(getDataDirectory(), "system_ce"); + } + /** {@hide} */ public static File getDataSystemCeDirectory(int userId) { return buildPath(getDataDirectory(), "system_ce", String.valueOf(userId)); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 7146448ad5d7c..bcc8d463e51db 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1496,7 +1496,9 @@ public class UserManager { } /** - * Returns information for all users on this device. + * Returns information for all users on this device, including ones marked for deletion. + * To retrieve only users that are alive, use {@link #getUsers(boolean)}. + *

* Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * @return the list of users that exist on the device. * @hide diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java index c1df28c387e51..7a2cbd06eb924 100644 --- a/keystore/java/android/security/GateKeeper.java +++ b/keystore/java/android/security/GateKeeper.java @@ -16,6 +16,7 @@ package android.security; +import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -32,7 +33,7 @@ public abstract class GateKeeper { public static IGateKeeperService getService() { IGateKeeperService service = IGateKeeperService.Stub.asInterface( - ServiceManager.getService("android.service.gatekeeper.IGateKeeperService")); + ServiceManager.getService(Context.GATEKEEPER_SERVICE)); if (service == null) { throw new IllegalStateException("Gatekeeper service not available"); } diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index eeb20bf03d123..1e715f93d0411 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -1588,7 +1588,7 @@ public class LockSettingsService extends ILockSettings.Stub { } final IBinder service = - ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"); + ServiceManager.getService(Context.GATEKEEPER_SERVICE); if (service != null) { service.linkToDeath(new GateKeeperDiedRecipient(), 0); mGateKeeperService = IGateKeeperService.Stub.asInterface(service); diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 408454286aeed..0cf517274f30e 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -3425,7 +3425,7 @@ public class AccountManagerService /** {@hide} */ @NonNull public AccountAndUser[] getAllAccounts() { - final List users = getUserManager().getUsers(); + final List users = getUserManager().getUsers(true); final int[] userIds = new int[users.size()]; for (int i = 0; i < userIds.length; i++) { userIds[i] = users.get(i).id; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f2fde0f91e402..a560c83ef92ed 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -19352,10 +19352,18 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && !mOnlyCore) { UserManagerService.enforceSerialNumber( Environment.getDataUserDeDirectory(volumeUuid, userId), userSerial); + if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) { + UserManagerService.enforceSerialNumber( + Environment.getDataSystemDeDirectory(userId), userSerial); + } } if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && !mOnlyCore) { UserManagerService.enforceSerialNumber( Environment.getDataUserCeDirectory(volumeUuid, userId), userSerial); + if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) { + UserManagerService.enforceSerialNumber( + Environment.getDataSystemCeDirectory(userId), userSerial); + } } synchronized (mInstallLock) { @@ -19424,6 +19432,10 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); .listFilesOrEmpty(Environment.getDataUserDeDirectory(volumeUuid))); Collections.addAll(files, FileUtils .listFilesOrEmpty(Environment.getDataUserCeDirectory(volumeUuid))); + Collections.addAll(files, FileUtils + .listFilesOrEmpty(Environment.getDataSystemDeDirectory())); + Collections.addAll(files, FileUtils + .listFilesOrEmpty(Environment.getDataSystemCeDirectory())); for (File file : files) { if (!file.isDirectory()) continue; diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index a8cf110655f80..a85064b70f22a 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -65,6 +65,8 @@ import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; import android.os.storage.StorageManager; +import android.security.GateKeeper; +import android.service.gatekeeper.IGateKeeperService; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -87,6 +89,7 @@ import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; +import com.android.server.SystemService; import com.android.server.am.UserState; import libcore.io.IoUtils; @@ -119,6 +122,7 @@ import java.util.List; * */ public class UserManagerService extends IUserManager.Stub { + private static final String LOG_TAG = "UserManagerService"; static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE private static final boolean DBG_WITH_STACKTRACE = false; // DO NOT SUBMIT WITH TRUE @@ -367,6 +371,31 @@ public class UserManagerService extends IUserManager.Stub { } } + public static class LifeCycle extends SystemService { + + private UserManagerService mUms; + + /** + * @param context + */ + public LifeCycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mUms = UserManagerService.getInstance(); + publishBinderService(Context.USER_SERVICE, mUms); + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { + mUms.cleanupPartialUsers(); + } + } + } + @VisibleForTesting UserManagerService(File dataDir) { this(null, null, new Object(), dataDir); @@ -408,25 +437,6 @@ public class UserManagerService extends IUserManager.Stub { } void systemReady() { - // Prune out any partially created, partially removed and ephemeral users. - ArrayList partials = new ArrayList<>(); - synchronized (mUsersLock) { - final int userSize = mUsers.size(); - for (int i = 0; i < userSize; i++) { - UserInfo ui = mUsers.valueAt(i).info; - if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) { - partials.add(ui); - } - } - } - final int partialsSize = partials.size(); - for (int i = 0; i < partialsSize; i++) { - UserInfo ui = partials.get(i); - Slog.w(LOG_TAG, "Removing partially created user " + ui.id - + " (name=" + ui.name + ")"); - removeUserState(ui.id); - } - mAppOpsService = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); @@ -447,6 +457,27 @@ public class UserManagerService extends IUserManager.Stub { null, mHandler); } + void cleanupPartialUsers() { + // Prune out any partially created, partially removed and ephemeral users. + ArrayList partials = new ArrayList<>(); + synchronized (mUsersLock) { + final int userSize = mUsers.size(); + for (int i = 0; i < userSize; i++) { + UserInfo ui = mUsers.valueAt(i).info; + if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) { + partials.add(ui); + } + } + } + final int partialsSize = partials.size(); + for (int i = 0; i < partialsSize; i++) { + UserInfo ui = partials.get(i); + Slog.w(LOG_TAG, "Removing partially created user " + ui.id + + " (name=" + ui.name + ")"); + removeUserState(ui.id); + } + } + @Override public String getUserAccount(int userId) { checkManageUserAndAcrossUsersFullPermission("get user account"); @@ -2472,8 +2503,23 @@ public class UserManagerService extends IUserManager.Stub { "Destroying key for user " + userHandle + " failed, continuing anyway", e); } + // Cleanup gatekeeper secure user id + try { + final IGateKeeperService gk = GateKeeper.getService(); + if (gk != null) { + gk.clearSecureUserId(userHandle); + } + } catch (Exception ex) { + Slog.w(LOG_TAG, "unable to clear GK secure user id"); + } + // Cleanup package manager settings mPm.cleanUpUser(this, userHandle); + + // Clean up all data before removing metadata + mPm.destroyUserData(userHandle, + StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); + // Remove this user from the list synchronized (mUsersLock) { mUsers.remove(userHandle); @@ -2496,12 +2542,6 @@ public class UserManagerService extends IUserManager.Stub { AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX)); userFile.delete(); updateUserIds(); - - // Now that we've purged all the metadata above, destroy the actual data - // on disk; if we battery pull in here we'll finish cleaning up when - // reconciling after reboot. - mPm.destroyUserData(userHandle, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); } private void sendProfileRemovedBroadcast(int parentUserId, int removedUserId) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java index 1ae1a773b23ea..b53933e07f2bd 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java @@ -120,7 +120,7 @@ class Owners { // First, try to read from the legacy file. final File legacy = getLegacyConfigFileWithTestOverride(); - final List users = mUserManager.getUsers(); + final List users = mUserManager.getUsers(true); if (readLegacyOwnerFileLocked(legacy)) { if (DEBUG) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 476a559eaea3f..f59b2ff16482f 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -470,7 +470,7 @@ public final class SystemServer { } traceBeginAndSlog("StartUserManagerService"); - ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance()); + mSystemServiceManager.startService(UserManagerService.LifeCycle.class); Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); // Initialize attribute cache used to cache resources from packages.