diff options
| -rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 10 | ||||
| -rw-r--r-- | core/java/android/content/pm/UserInfo.java | 11 | ||||
| -rw-r--r-- | core/java/android/os/UserManager.java | 19 | ||||
| -rw-r--r-- | core/java/android/os/storage/IMountService.java | 23 | ||||
| -rw-r--r-- | core/java/android/os/storage/StorageManager.java | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/MountService.java | 10 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 13 |
8 files changed, 72 insertions, 25 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 544fd6a702cf..478164a8c2d0 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -16,11 +16,11 @@ package com.android.commands.pm; -import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; -import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; import android.accounts.IAccountManager; import android.app.ActivityManager; @@ -798,6 +798,10 @@ public final class Pm { flags |= UserInfo.FLAG_MANAGED_PROFILE; } else if ("--restricted".equals(opt)) { flags |= UserInfo.FLAG_RESTRICTED; + } else if ("--ephemeral".equals(opt)) { + flags |= UserInfo.FLAG_EPHEMERAL; + } else if ("--guest".equals(opt)) { + flags |= UserInfo.FLAG_GUEST; } else { System.err.println("Error: unknown option " + opt); return showUsage(); @@ -1356,7 +1360,7 @@ public final class Pm { System.err.println(" pm get-install-location"); System.err.println(" pm set-permission-enforced PERMISSION [true|false]"); System.err.println(" pm trim-caches DESIRED_FREE_SPACE [internal|UUID]"); - System.err.println(" pm create-user [--profileOf USER_ID] [--managed] [--restricted] USER_NAME"); + System.err.println(" pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME"); System.err.println(" pm remove-user USER_ID"); System.err.println(" pm get-max-users"); System.err.println(""); diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index 6e095959e162..e3050fee6dca 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -78,6 +78,12 @@ public class UserInfo implements Parcelable { public static final int FLAG_QUIET_MODE = 0x00000080; + /** + * Indicates that this user is ephemeral. I.e. the user will be removed after leaving + * the foreground. + */ + public static final int FLAG_EPHEMERAL = 0x00000100; + public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL; public int id; @@ -134,6 +140,11 @@ public class UserInfo implements Parcelable { public boolean isQuietModeEnabled() { return (flags & FLAG_QUIET_MODE) == FLAG_QUIET_MODE; } + + public boolean isEphemeral() { + return (flags & FLAG_EPHEMERAL) == FLAG_EPHEMERAL; + } + /** * Returns true if the user is a split system user. * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled, diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index c96305e7878e..c8abcef05fea 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -721,6 +721,25 @@ public class UserManager { } /** + * Checks if the calling app is running as an ephemeral user. + * + * @return whether the caller is an ephemeral user. + * @hide + */ + public boolean isEphemeralUser() { + return isUserEphemeral(UserHandle.myUserId()); + } + + /** + * Returns whether the specified user is ephemeral. + * @hide + */ + public boolean isUserEphemeral(int userId) { + final UserInfo user = getUserInfo(userId); + return user != null && user.isEphemeral(); + } + + /** * Return whether the given user is actively running. This means that * the user is in the "started" state, not "stopped" -- it is currently * allowed to run code through scheduled alarms, receiving broadcasts, diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index c6510f0d1d79..9b3f02d69e9f 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -25,8 +25,6 @@ import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.RemoteException; -import java.io.FileDescriptor; - /** * WARNING! Update IMountService.h and IMountService.cpp if you change this * file. In particular, the ordering of the methods below must match the @@ -1202,13 +1200,15 @@ public interface IMountService extends IInterface { } @Override - public void createUserKey(int userId, int serialNumber) throws RemoteException { + public void createUserKey(int userId, int serialNumber, boolean ephemeral) + throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(userId); _data.writeInt(serialNumber); + _data.writeInt(ephemeral ? 1 : 0); mRemote.transact(Stub.TRANSACTION_createUserKey, _data, _reply, 0); _reply.readException(); } finally { @@ -1283,7 +1283,8 @@ public interface IMountService extends IInterface { } @Override - public void prepareUserStorage(String volumeUuid, int userId, int serialNumber) + public void prepareUserStorage( + String volumeUuid, int userId, int serialNumber, boolean ephemeral) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); @@ -1292,6 +1293,7 @@ public interface IMountService extends IInterface { _data.writeString(volumeUuid); _data.writeInt(userId); _data.writeInt(serialNumber); + _data.writeInt(ephemeral ? 1 : 0); mRemote.transact(Stub.TRANSACTION_prepareUserStorage, _data, _reply, 0); _reply.readException(); } finally { @@ -2012,7 +2014,8 @@ public interface IMountService extends IInterface { data.enforceInterface(DESCRIPTOR); int userId = data.readInt(); int serialNumber = data.readInt(); - createUserKey(userId, serialNumber); + boolean ephemeral = data.readInt() != 0; + createUserKey(userId, serialNumber, ephemeral); reply.writeNoException(); return true; } @@ -2052,7 +2055,8 @@ public interface IMountService extends IInterface { String volumeUuid = data.readString(); int userId = data.readInt(); int serialNumber = data.readInt(); - prepareUserStorage(volumeUuid, userId, serialNumber); + boolean ephemeral = data.readInt() != 0; + prepareUserStorage(volumeUuid, userId, serialNumber, ephemeral); reply.writeNoException(); return true; } @@ -2376,15 +2380,16 @@ public interface IMountService extends IInterface { public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) throws RemoteException; - public void createUserKey(int userId, int serialNumber) throws RemoteException; + public void createUserKey(int userId, int serialNumber, boolean ephemeral) + throws RemoteException; public void destroyUserKey(int userId) throws RemoteException; public void unlockUserKey(int userId, int serialNumber, byte[] token) throws RemoteException; public void lockUserKey(int userId) throws RemoteException; public boolean isUserKeyUnlocked(int userId) throws RemoteException; - public void prepareUserStorage(String volumeUuid, int userId, int serialNumber) - throws RemoteException; + public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, + boolean ephemeral) throws RemoteException; public ParcelFileDescriptor mountAppFuse(String name) throws RemoteException; } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 7f36a9866eb7..beda16996e0e 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -966,9 +966,9 @@ public class StorageManager { } /** {@hide} */ - public void createUserKey(int userId, int serialNumber) { + public void createUserKey(int userId, int serialNumber, boolean ephemeral) { try { - mMountService.createUserKey(userId, serialNumber); + mMountService.createUserKey(userId, serialNumber, ephemeral); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -1002,9 +1002,10 @@ public class StorageManager { } /** {@hide} */ - public void prepareUserStorage(String volumeUuid, int userId, int serialNumber) { + public void prepareUserStorage( + String volumeUuid, int userId, int serialNumber, boolean ephemeral) { try { - mMountService.prepareUserStorage(volumeUuid, userId, serialNumber); + mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, ephemeral); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 473eff654eac..184f8905acaf 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2716,12 +2716,13 @@ class MountService extends IMountService.Stub } @Override - public void createUserKey(int userId, int serialNumber) { + public void createUserKey(int userId, int serialNumber, boolean ephemeral) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); waitForReady(); try { - mCryptConnector.execute("cryptfs", "create_user_key", userId, serialNumber); + mCryptConnector.execute("cryptfs", "create_user_key", userId, serialNumber, + ephemeral ? 1 : 0); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } @@ -2797,13 +2798,14 @@ class MountService extends IMountService.Stub } @Override - public void prepareUserStorage(String volumeUuid, int userId, int serialNumber) { + public void prepareUserStorage( + String volumeUuid, int userId, int serialNumber, boolean ephemeral) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); waitForReady(); try { mCryptConnector.execute("cryptfs", "prepare_user_storage", escapeNull(volumeUuid), - userId, serialNumber); + userId, serialNumber, ephemeral ? 1 : 0); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index d94e5f491f75..ab8e5a771f67 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -16450,7 +16450,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (userDir.exists()) continue; try { - sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber); + sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, user.isEphemeral()); UserManagerService.enforceSerialNumber(userDir, user.serialNumber); } catch (IOException e) { Log.wtf(TAG, "Failed to create user directory on " + volumeUuid, e); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index e045758ccd65..4497e4dd73b6 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -306,13 +306,13 @@ public class UserManagerService extends IUserManager.Stub { } void systemReady() { - // Prune out any partially created/partially removed users. + // Prune out any partially created, partially removed and ephemeral users. ArrayList<UserInfo> partials = new ArrayList<>(); synchronized (mUsersLock) { final int userSize = mUsers.size(); for (int i = 0; i < userSize; i++) { UserInfo ui = mUsers.valueAt(i); - if ((ui.partial || ui.guestToRemove) && i != 0) { + if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) { partials.add(ui); } } @@ -1675,6 +1675,10 @@ public class UserManagerService extends IUserManager.Stub { } } } + + if (parent != null && parent.isEphemeral()) { + flags |= UserInfo.FLAG_EPHEMERAL; + } userId = getNextAvailableId(); userInfo = new UserInfo(userId, name, null, flags); userInfo.serialNumber = mNextSerialNumber++; @@ -1703,12 +1707,13 @@ public class UserManagerService extends IUserManager.Stub { } } final StorageManager storage = mContext.getSystemService(StorageManager.class); - storage.createUserKey(userId, userInfo.serialNumber); + storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral()); for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { final String volumeUuid = vol.getFsUuid(); try { final File userDir = Environment.getDataUserDirectory(volumeUuid, userId); - storage.prepareUserStorage(volumeUuid, userId, userInfo.serialNumber); + storage.prepareUserStorage( + volumeUuid, userId, userInfo.serialNumber, userInfo.isEphemeral()); enforceSerialNumber(userDir, userInfo.serialNumber); } catch (IOException e) { Log.wtf(LOG_TAG, "Failed to create user directory on " + volumeUuid, e); |