Multi-User Android - The Complete Guide (AnDevCon Boston 2014)

29
Multi-User Android @ronubo Ron Munitz PSCG

Transcript of Multi-User Android - The Complete Guide (AnDevCon Boston 2014)

Multi-User Android@ronuboRon Munitz

PSCG

This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/

© Copyright Ron Munitz 2014

PSCG

PSCGAbout://Ron Munitz

● Distributed Fault Tolerant Avionic Systems○ Linux, VxWorks, very esoteric libraries, 0’s and 1’s

● Highly distributed video routers○ Linux

● Real Time, Embedded, Server bringups○ Linux, Android , VxWorks, Windows, devices, BSPs, DSPs,...

● Distributed Android○ Rdroid? Cloudroid? Too busy working to get over the legal naming, so

no name is officially claimed for my open source.

● What currently keeps me busy:○ Running the PSCG, a Embedded/Android consulting and Training ○ Teaching for New Circle○ Lecturing at Afeka’s college of Engineering ○ Amazing present, endless opportunities. (Wish flying took less time)

PSCG

PSCGAndroid Multi-User Support

● Support for multiple users in Android has been around for a while (ever since Jelly Bean came out)○ AOSP: 4.0.9999999

● But has only been officially acknowledged in JB 4.2, for tablets only.○ Patent restriction?○ Revenue sharing issue?○ Phone being personal?

PSCGAndroid Multi-User Support

● Multiple user support allows several users to share the same tablet/phone

● And yet, maintain individual settings, configurations, accounts, files on one device.

* Note: The Multi-User implementation is still evolving. This presentation represents the current android-4.4.2_r2 based release.

PSCGEnabling Multi-User - a teaser

● This method will work for a “modern” rooted device

● Such as the android Emulator in the Android SDK!

● Pre-requisites for our “teaser”:○ Android version >= 4.2.2 emulator○ adb

PSCGEnabling Multi-User - a teaser

● First, we must enable multi user:adb shell setprop fw.max_users <number_of_users>

● Then, we can add, remove and administrate users, using the PackageManager and ActivityManager command line interfaces:○ pm create-user <user_name>○ pm remove-user <user_id>○ pm list-users○ am switch-users <user_id>○ …

● Let’s see this in action!

PSCGUser Id allocation

● KitKat’s user id granting:○ First user ID: 0 - This is the default administrator.

■ AKA the “Primary user”.○ Second user: 10○ Then comes 11○ And 12○ …○ Last user ID would be 10+max_users-1

● Unless modified by a custom ROM● Or by Google/Android themselves

○ I remember times where the second user id was 2.

PSCGSo what really happens behind the scenes?

We will review the following aspects:● User's private data space● Creating a new user● Switching between users● Processes and threads

PSCGUser's private data space: The past

Past (def.): Android versions prior to JB 4.2● In previous versions of Android all user data was saved

under /data/data

● This directory held a separate directory for each application installed○ Each having their own uid/gid

● When an application (package name <package name>) needs to save data to the disk (not to the external SD device) it would save it to /data/data/<package name>

PSCGUser's private data space: The Present

Present (def.) - anything after the past.● Every user has his/her own directory under

/data/user/<user Id>● By default, there is only one user (Primary) with Id == 0● The Primary user's directory is /data/user/0

○ However this is actually a symlink to /data/data● When a new user account is created, a new directory is

also created under /data/user/<user id>. ● Every application that is installed on the device from this

moment on will also create a directory for this user under this directory○ Unless explicitly excluded

PSCGActivityStackSupervisor

● ActivityStackSupervisor* contains 2 stacks:○ A stack for all Launcher apps (“Home Stack”)○ A stack for all other apps

● At any point in time there is only one stack in focus○ so when the user is using the Launcher, the

Launcher stack has focus○ and when the user launches an app, the app stack

gets focus.

Note: Currently the API allows a user to have a split screen (split a stack into 2 sub-stacks), but this is not used anywhere in the code.

*@see frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java)

PSCGCreating a new user● UserManager finds the next available user id● Creates a new UserInfo for this is● Clones the directory structure of user 0 (i.e. creates a directory for each

package installed on the system under the new user's directory)● Adds the new user Id to /data/system/users/userlist.xml● Creates a file /data/system/users/<userId.xml> and writes UserInfo to it● Creates a new directory under /data/user/<user Id>● Creates a directory for all the apps installed (even if the user doesn’t have

permissions use them)● Broadcasts a ACTION_USER_ADDED Intent to the system

PSCGSwitching Users

The ActivityManager ● Adds the new user to the list of mStartedUsers● Changes the current user's Id to the new Id● Tells WindowsManagerService* that there was a user

switch.WindowsManagerService then:○ Sets all previous user’s windows to hidden○ If this user was previously active then all this user’s

windows are moved up● Sends a delayed message to all services that are user

aware (discussed later)

PSCGSwitching Users (cont.)

The Activity Manager● Tells the ActivityStackSupervisor to move all previous

activities of that user up the stack● Tells UserManagerService** who the new user is● If there were no previous activities present for this user,

then the HOME activity is launched● Sends a broadcast of Intent

ACTION_USER_SWITCHED and ACTION_USER_STARTING (services that use this are discussed later)

*frameworks/base/services/java/com/android/server/wm/WindowManagerService.java**frameworks/base/services/java/com/android/server/pm/UserManagerService.java

PSCGUser Switching and Services

● When a user has left the building, there is no point in working for them

● Yet the new user has to be satisfied● The Android Services, initiated by the System Server

and the /init/ script run in some sort of an endless loop● So they must be notified, and adjust to the changes.● Let’s see some examples for that

PSCGUser Switching and Services

● BluetoothManagerService: Turns off Bluetooth adapter● TextServicesManagerService: The current clipboard is

switched with the new user’s clipboard ( If this user has not been active since the device was turned on, then a new clipboard is created for the user)

● InputMethodManagerService: unbinds the service(keyboard) from all apps and resets its internal state

● WallpaperManagerService: Replaces the current wallpaper with the new user’s wallpaper

PSCGUser Switching and Services

● AudioService: Stops all music● VibratorService: Reloads new user preferences

regarding vibration services● UsbService: Resets usb settings to MTP● PowerManagerService: Loads new user’s brightness

level, screen off timeout for user, screensaver preferences, etc.

● InputManagerService: Loads user’s preferences (pointer speed, show touch events, etc.)

● LocationManagerService: Let’s all apps know that location providers have changed (new user has new content providers)

PSCGProcesses and Threads

Let’s examine an excerpt of a list of processes currently running on a system:

We can see that although only one launcher is currently active, both processes remain active.This design consideration speeds up user switching.*Unnecessary processes will eventually be OOM killed.

# adb shell psUSER PID ... NAMEu0_a2 1013 com.android.launcheru0_a15 1115 com.android.contactsu1_a2 1455 com.android.launcheru1_system 1473 com.android.settings

PSCGuid/gid/permission trivia

Q1: How is a user's uid decided upon?A1: uid = user_Id*100,000+app_Id

This way, any system method that is called through the binder, can tell who the caller is by the uid sending the Binder request

PSCGuid/gid/permission trivia

Q2: What about the “hardcoded” Ids? Why is “root” 0? Why is “system” 1000? How is hardware access restricted by the kernel?

A2: @see /system/core/include/private/android_filesystem_config.h

@see your favorite init.rc (Especially mkdir and service “group”s).

PSCGuid/gid/permission trivia

Q3: How are permissions enforced?

A3: To answer this question, we will need consult the oracle. Or just grep the permission, and see what the different services, and or apps define

This is pure “software”. No linux magic.

Shell Tip: pm list permissions pm list permission-groups

PSCGExternal Storage

● When the external storage is emulated, it holds separate directories for each user:○ User 0 has access to /storage/emulated/0○ User 10 has access to /storage/emulated/10

● It does not do it by not directly mounting /dev/block/… ● But rather by FUSE-ing it● FUSE: Filesystem in USErspace● For every process, the /sdcard path resolves to the

correct /storage/emulated/<userId> path

PSCGExternal Storage

● The external storage requires 2 out of 3 parameters to be set at boot time (init.rc):○ EMULATED_STORAGE_SOURCE - At boot time, system mounts a

single emulated external storage FUSE daemon here (/mnt/shell/emulated)

○ EMULATED_STORAGE_TARGET - After the Zygote forks, it bind mounts the appropriate user-specific subdirectory from under the FUSE daemon here (/storage/emulated/<userId>)

○ EMULATED_STORAGE - This is where the process will look for the sdcard (/storage/emulated/legacy)

PSCGExternal Storage● Starting in Android 4.4, the owner, group and modes of files on external

storage devices are now synthesized based on directory structure. ● This enables apps to manage their package-specific directories on external

storage without requiring they hold the broad WRITE_EXTERNAL_STORAGE permission.

● For example, the app with package name com.example.foo can now freely access Android/data/com.example.foo/ on external storage devices with no permissions

● This could be a nice thing○ Eliminates unprivileged writes to a “global” area on the sdcard○ Eliminates garbage keeping after package removal

● Most developers beg to differ...

PSCGExternal StorageOr: how to make your developers (and users) ANGRY

PSCGMultiuser Application awareness

● There is a public class available for that.● class UserManager● It doesn’t mean that you can do much with it. ● The truth is that you currently can’t do much

unless you are a system application that has the MANAGE_USERS permission

● Still the future looks promising.

PSCGJustifying the first slide

http://developer.android.com/reference/android/os/UserManager.html#isUserAGoat()

boolean isUserAGoat()Used to determine whether the user making this call is subject to teleportations

*Credit for the cover image:http://www.pheasantviewgoatsoap.com/files/QuickSiteImages/goats-large.jpg