Access restrictions
Your TomTom BRIDGE device comes out of the box with two user access profiles:
- You (Owner)
- User
In owner profile, all settings are accessible, all apps are displayed in the application browser and ADB access is permitted. In user profile, settings and apps can be made inaccessible by the Owner. ADB access is not permitted.
The Owner can select which apps and settings are permitted in user mode by selecting checkboxes in the settings/users menu on the TomTom BRIDGE device.
Selecting which settings the "User" is allowed to change:
Selecting which applications the "User" is allowed to use:
Owner and restricted user
There are two types of users that can run a TomTom BRIDGE: an owner ("Owner") and restricted users ("User"). The Owner can do everything with the device that you can do with any other non-rooted Android device. The User can be enabled by the Owner, who can define what that user is allowed to do on the device: which applications are allowed to be started, can settings be changed, etc.
You are the Owner that defines a configuration for the TomTom BRIDGE that your customers will use as a User. This is because it will make it impossible for that user to change the configuration of the device and perhaps use it for other means than you intended.
You will find the user profiles under Settings / Users
. To change the definition of a User, tap
the settings icon to the right of it. Here you can select which apps the user is allowed to start,
which settings it is allowed to change, etc.
The "Clear Personal Data" option in the Settings / Backup & reset
menu, will only clear the data
for the current User when that user is not the Owner. When the Owner selects this option, all the
personal data of all users will be cleared.
Multi user boot sequence
Standard Android will always boot into the owner profile which makes sense for mobile phone and generic tablet scenarios. The TomTom BRIDGE has a different requirement in that it is being configured by the Owner to be used by a User, whom we do not want to have to enter a PIN each time they use the device. It is also not desirable to boot into the Owner profile every time since we do not want the end-user to be able to change the configuration. Make sure you have set a private PIN code for the Owner profile to lock this down completely.
This is why the TomTom BRIDGE will start up using the last used profile. To accomplish this we must allow Android boot in Owner profile, after which we switch to the last selected user as soon as possible to finish the boot process. The user holding the device cannot interfere with this so it will be transparent to him.
This does pose some challenges for developers though, since apps started
on android.intent.action.BOOT_COMPLETED
will get started for both Owner and User! They might
therefore have issues with hardware features being claimed by the Owner while the User is trying to
get at it too. The TomTom BRIDGE built in apps already handle these situations gracefully but if you
plan to add your own apps to the device configuration, you must make them aware of this as well.
When the user profile is switched, all running applications of any other user will receive
the ACTION_USER_BACKGROUND
intent to inform them that they will be pushed to the background. This
is what is happening at boot time too. Adding the following to your application will make it able to
respond to the user switch:
1public class MyApplication extends Application {2 private static final String TAG = MyApplication.class.getSimpleName()34 /**5 * Default implementation of the broadcast receiver which is responsible for killing the6 * current application if a user goes to the background.7 */8 private class BackgroundUserReceiver extends BroadcastReceiver {9 @Override10 public void onReceive(final Context context, final Intent intent) {11 if ((intent != null) && Intent.ACTION_USER_BACKGROUND.equals(intent.getAction())) {12 killSelf();13 }14 }15 }1617 @Override18 public void onCreate() {19 super.onCreate();2021 // First check if the application was started for correct user.22 if (!checkCorrectUser(this)) {23 return;24 }2526 // If it is, then register a receiver for the cases when a user is switched.27 registerReceiver(new BackgroundUserReceiver(), new IntentFilter(Intent.ACTION_USER_BACKGROUND));28 }2930 // ...31}
This will check if this application is run by the current foreground user. When it receives the
message that this application is being moved to the background because a different user became
active, the BackgroundUserReceiver
will stop this application, thus making sure no two copies for
different users of this application remain active at the same time. Example implementations of the
helper functions look like this:
1/**2 * Checks if the current user is the same user for which the application is started. If not -3 * kills the process of the application.4 *5 * @return true if the application is started for correct user, false otherwise.6 */7private static boolean checkCorrectUser(final Context context) {8 assert context != null;910 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {11 final long currentUserId = getCurrentUserId(context);12 final long lastUserId = getLastUserId(context);13 Log.i(TAG, "currentUser=" + currentUserId + " lastUser=" + lastUserId);1415 if (((currentUserId == 0) && (lastUserId != 0)) || ((currentUserId != 0) && (lastUserId == 0))) {16 Log.w(TAG, "App was started for the wrong user. Killing the process.");17 killSelf();1819 return false;20 }21 }22 return true;23}2425// Suppress lint since explicit check for the current version is done above.26@SuppressLint("NewApi")27private static long getCurrentUserId(final Context context) {28 assert context != null;2930 long userSerialNumber = 0;31 final UserHandle userHandle = android.os.Process.myUserHandle();32 final UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);33 if (userManager != null) {34 userSerialNumber = userManager.getSerialNumberForUser(userHandle);35 }36 return userSerialNumber;37}3839// Suppress lint since explicit check for the current version is done above.40@SuppressLint("NewApi")41private static long getLastUserId(final Context context) {42 assert context != null;4344 return Settings.Global.getInt(context.getContentResolver(), "last_user_id", 0);45}4647private static void killSelf() {48 new Handler().post(new Runnable() {49 @Override50 public void run() {51 android.os.Process.killProcess(android.os.Process.myPid());52 }53 });54}
Note that most applications will not have a problem with running twice on the same device as different users. Only add the above if your application cannot function with two instances running.