Multi-user support is one of the few remaining things a desktop OS can do that Android can't. The "coffee table tablet" use case would greatly benefit from a multi-user setup, as would an enterprise user who wants to keep work and home separate. It's been a top 20 item on the Android bug tracker since the debut of Honeycomb, so there is certainly demand for it.
As we've seen from my previous experiments in sticking my nose where it doesn't belong, Google likes to leave breadcrumbs in shipping products for the astute observer to find, and the multi-user situation is no different. After a bit of research, I can tell you that Google is listening. There is a surprising amount of multi-user work being done on Android - some of it is even working on devices right now.
Before we jump into things, we're going to need to learn some vocabulary. "AOSP" is Android Open Source Project, you should know that one. It's the publicly available code base for Android. A "commit" is a code push to this code repository. You're supposed to include a helpful comment with your commit, telling people what the new code is supposed to accomplish. This is Android code, so the commit comments are written by Googlers. In other words: they're accurate.
Now, on to the evidence:
The First Clue
You can't see it, but there is multi user support in there somewhere.
I was originally clued into the idea of multi-user code already existing by Abhisek Devkota, aka "ciwrl," CyanogenMod's Head Moderator. The guys at CM had stumbled upon some interesting sounding methods named "SetCurrentUser" and "onUserChanged." These methods were found in LockPatternKeyguardView.java, a file for Android's pattern unlock. Here's the whole section:
public void onUserChanged(int userId) { mLockPatternUtils.setCurrentUser(userId); updateScreen(getInitialMode(), true); }
I'm no expert, but this looks pretty straightforward: when the user changes, switch the lock screen over to the new user's lock screen, and redraw the screen so the user can see these changes. It sounds like pattern unlock is listening for a user switch!
There's way more to this than just that one section. Ciwrl also pointed out a few commits to me, and if you start digging through the public AOSP repository, you'll start noticing tons of work related to multi-user functionality. After a bit of work, I've been able to piece together a decent timeline of multi-user upgrades to the AOSP code base.
The Timeline Of Commits
Please note that, just because something is mentioned, doesn't mean it is 100% working, or even working at all. And, just like any big change to Android, the biggest problem is ecosystem support: you have to implement this without breaking everything else. So consider this to be merely a peak at what has been worked on, and nothing more.
Direct quotes of commit comments are in bold, and my attempt at translations are in regular text:
April 14th, 2011 - "Plumbing in PackageManager and installd for multi-user support."
By Amith Yamasani, A Google Engineer
- Create /data/user directory and symlink /data/user/0 -> /data/data for backward compatibility - A big part of switching to a multi-user OS will be moving all of the global settings, files, and apps from wherever they are now, to a users/[username] directory, while remaining backwards compatible and not breaking anything. Luckily, Android is built on Linux, which supports all sorts of handy file system tricks, like a "symlink." A symlink allows you to move a directory, but leave behind a pointer for anything that goes looking in the old location. Here, they moved the /data/data directory to /data/user/0, and made a symlink, so anything looking in /data/data will know to look in /data/user/0. In theory, nothing will break. In theory.
- Create data directories for all packages for new user - "Package" is just technical speak for "app." When a new user is created, the system will now make them their own copies of app data for every currently installed app.
- Remove data directories when removing a user - Then you'll want to delete all that data if the user is removed.
- Create data directories for all users when a package is created - Now, when you install Angry Birds, everyone gets a separate save file.
- Clear / Remove data for multiple users - I assume this is talking about the "clear data" button in app info, and the uninstall procedure. This brings up a good example of how complicated this can be. What happens to User 1's data when User 2 hits clear data?
- pm commands for createUser and removeUser (will be disabled later)
May 4th, 2011 - "Multi-user - 1st major checkin"
- Switching activity stacks - In other words, change the running apps when a user switch happens. The back button stack would change, the recent apps would change, etc.
- Cache ContentProvider per user - Content providers share data between multiple applications. Anything that is shared will use a Content Provider, so, for instance, Contacts and Calendar info. These are per-user now.
- Long-press power to switch users (on phone) - User Interface?! I wish I could find this somewhere, but I can't. Maybe this wasn't UI, and was just a dirty testing hack.
- Added ServiceMap for separating services by user - A new part of Activity Manager for handling background services on a per-user basis.
- Launch PendingIntents on the correct user's uid
- Commands added to pm and am to allow creating and switching profiles. - "pm" stands for "PackageManger," which deals with information about installed applications. "am" stands for "ActivityManager." An activity is basically the any piece of UI in Android - usually full screen windows. Basically, this is Android's first lesson on how to deal with multiple users. You'll need to create separate user profiles, with different apps settings, and different sets of running apps.
March 13th, 2012 - "Package restrictions per user"
By Amith Yamasani
- Packages can be enabled/disabled per user. This requires maintaining stopped/launched states and enabled / disabled components and packages per user. - Well, there you go, per-user app disabling.
- Refactored pm.Settings and PackageSettingsBase to keep track of states per user. - Similar to the above, per user Package Manager settings.
- Migrated the stopped-packages.xml to users/<u>/package-restrictions.xml - More global settings being moved to per-user settings.
- Changed intent resolution to handle individual user restrictions. - A good example of intent resolution is the app picker box that pops up when more than one application can be used for an action. It matches the intent (like "I want to open a web page") with the programs that can handle it. So if 1 user prefers Chrome and another user prefers the stock browser, it can do that.
- Bunch of IPackageManager calls now have a userId argument.
March 22nd, 2012 - "User management and switching"
By Amith Yamasani
- Broadcast intents that get sent out when users are added/removed/switched. - When a user switch happens, you're going to need to run around to everything on the system and let it know about it.
- More work on generating user-specific information in package manager queries.
- APIs to update user name and query a user by id.
- Removed Package.mSetStopped and mSetEnabled, since they're not user specific. - You can now ask Package Manager about installed apps for individual users.
- User removal:
- Cleanup ActivityManager, PackageManager, WallpaperManager, AppWidgetService
and AccountManager. - Shutdown processes belonging to the user. - When a user is deleted, you're going to want to wipe out all of their settings and kill all their apps.
- Cleanup ActivityManager, PackageManager, WallpaperManager, AppWidgetService
- Lock the screen when switching users, to force unlocking. - Sounds like you would pick a user, then get the unlock screen, which would make sense and be secure.
March 28th, 2012 - "Lockscreen settings per user"
By Amith Yamasani
- Move all lockscreen related settings to LockSettingsService.
- LockPatternUtils uses this through IPC instead of Secure settings.
- Migrate old settings to new database managed by LockSettingsService. - It sounds like the lock screen is the primary interface for user switching, so it needed a rewrite.
- Passwords and patterns are stored in a new per-user location, except for the primary user, for backward compatibility. - Like I said, doing this without breaking everything is going to be a challenge, so it looks like, initially, not all users will be equal as far as the system is concerned, for compatibility reasons. That doesn't necessarily mean end users will see the difference.
- KeyguardViewMediator and LockPatternKeyguardView listen for changes to user and updates the lockscreen. - This is referencing the code I showed, above. Pattern unlock is listening for a user switch! Currently the user switch never happens, but it's ready for it.
- Settings provider will look for Lock settings in the LockSettings service now for the entries that used to be stored in Settings. - Ah, so the lock screen settings used to be stored with all the other settings, but they have been spun off into their own file. This is another security measure. It sounds like, before, you would need to load the entire settings file to get the lock screen settings. Now you load as little as possible until the lock screen can verify the user.
So How Much Of This Actually Works?
Of course, the question arises when reading those comments, how much of this is actually in Android right now? All of those commit dates are pre-Jelly Bean, and some are pre-Ice Cream Sandwich, so some of this stuff must be live, right?
One of the more interesting and new-ish Android files is called "UserManager.java." It references a "userlist.xml" file in /data/system/users, so that sounds like a good place to start. Here it is in Jelly Bean:
Oh my. You're telling me this works right now?!
That is a live, working, multi-user directory structure. A single-user OS would just store everything under /data/system, but the fact that this is already storing things in a "user" folder is just phenomenal progress. There are settings for app widgets I have on my home screen, apps I have installed and disabled, and my wallpaper settings. It's been right under our noses this whole time: Jelly Bean is a multi-user OS, with only 1 user. I am User 0.
Let's take a closer look at some of these files:
As we can see in the "<users>" section of "userlist.xml," there is only 1 user, User 0. A quick look at users/0/appwidgets.xml confirms that user is me, because those are the widgets on my home screen. It's interesting that app widgets are here, but there's no mention of the actual app shortcuts.
"0.xml" will probably, one day, house things like my name and my profile picture, but for right now, my name is just "Primary." If you recall, we've heard of "Primary" before in the March 28th, 2012 commit: "Passwords and patterns are stored in a new per-user location, except for the primary user, for backward compatibility." Primary is the least exotic and most backwards compatible user.
"Accounts.db" is an SQLite database. It contains the accounts listed under the "Accounts" section of settings, in my case, Google and Dropbox. It also contains the full list of every Google service I've ever used, my preferred language, and my authtokens. So it looks like accounts and syncing is on a per-user basis now, too.
Package-restrictions.xml has a seemly complete list of apps on my phone, and their enabled/disabled status. Toward the middle you can see "com.google.android.email enabled=3" which means I've gone to app info and hit the disabled button for it. So, as we saw in the commits, each user can enable/disable the apps of their choosing.
In the April 14th 2011 update, we saw a switch from /data/data to /data/user/0, so let's check that out on Jelly Bean:
Wow. The magic of Linux. Thanks to the symlink, the majority of apps are now storing their data in a user directory, instead of dumping them in a global directory. There's almost 100 directories in here. I was concerned about 3rd party app support, but it looks like most app is ready for more users.
Conclusion
So, in my very-much-non-expert-opinion, it looks like the following things are separated for multiple users: lock screens, installed applications, running applications, application data, default applications, home screen widgets, accounts, syncing, and language.
And the following things still need to be worked on: Namely, every piece of UI. You need a user switching screen, an entire settings section for managing users, setting permissions, taking or picking user avatars, names, etc. You'll also need a way to know what user is currently logged in. There also doesn't appear to be separate settings for home screen shortcuts, and probably a million other settings. And who knows how 3rd party apps would really deal with a massive change like this. Lots of testing needs to happen.
The first commit was over a year ago, and the last one we know about was 4 months ago. A lot of work has already gone into multiple user account support, but I'm sure there's still a lot more work to be done. Keep plugging away Googlers! I'll be watching...