This page provides an overview of the enterprise APIs, features, and behavior
changes that are available in the Android 9.

## Work profile user interface

Android 9 (API level 28) includes user interface changes in the default
launcher to help users separate personal and work apps. Device manufacturers
supporting this can present users' apps in separate work and personal tabs.
We've also made it easier for device users to turn the work profile on and off by
including a switch in the launcher's work tab.
![](https://developer.android.com/static/images/about/versions/pie/p-work-profile.jpg) **Figure 1.** The default launcher's personal tab and work tab with work profile switch

When provisioning work profiles and managed devices, Android 9 includes
animated illustrations to help device users understand these features.

### Switch apps across profiles

Android 9 includes APIs to launch another instance of an app in a different
profile to help users switch between accounts. For example, an email app can
provide a UI that lets the user switch between the personal profile and the work
profile to access two email accounts. All apps can call these APIs to launch the
main activity of the same app if it's already installed in the other profile. To
add cross-profile account switching to your app, follow the steps below calling
methods of the
[`CrossProfileApps`](https://developer.android.com/reference/android/content/pm/CrossProfileApps) class:

1. Call [`getTargetUserProfiles()`](https://developer.android.com/reference/android/content/pm/CrossProfileApps#getTargetUserProfiles()) to get a list of profiles you can launch another instance of the app in. This method checks that the app is installed in the profiles.
2. Call [`getProfileSwitchingIconDrawable()`](https://developer.android.com/reference/android/content/pm/CrossProfileApps#getProfileSwitchingIconDrawable(android.os.UserHandle)) to get an icon that you can use to represent another profile.
3. Call [`getProfileSwitchingLabel()`](https://developer.android.com/reference/android/content/pm/CrossProfileApps#getProfileSwitchingLabel(android.os.UserHandle)) to get localized text that prompts the user to switch profiles.
4. Call [`startMainActivity()`](https://developer.android.com/reference/android/content/pm/CrossProfileApps#startMainActivity(android.content.ComponentName,%20android.os.UserHandle)) to launch an instance of your app in another profile.

Check that the main activity you want to launch is declared in your app's
manifest file, with an [`ACTION_MAIN`](https://developer.android.com/reference/android/content/Intent#ACTION_MAIN) intent action, and includes
a [`CATEGORY_LAUNCHER`](https://developer.android.com/reference/android/content/Intent#CATEGORY_LAUNCHER) intent category.

### Programmatically turn work profiles on or off

The default launcher (or apps that have the permission `MANAGE_USERS` or
`MODIFY_QUIET_MODE`) can turn the work profile on or off by calling
[`UserManager.requestQuietModeEnabled()`](https://developer.android.com/reference/android/os/UserManager#requestQuietModeEnabled(boolean,%20android.os.UserHandle)). You can
inspect the return value to know if the user needs to confirm their
credentials before the state changes. Because the change might not happen
instantly, listen for the
[`ACTION_MANAGED_PROFILE_AVAILABLE`](https://developer.android.com/reference/android/content/Intent#ACTION_MANAGED_PROFILE_AVAILABLE) or
[`ACTION_MANAGED_PROFILE_UNAVAILABLE`](https://developer.android.com/reference/android/content/Intent#ACTION_MANAGED_PROFILE_UNAVAILABLE)
broadcast to know when to update the user interface.

Your app can check the status of the work profile by calling
[`UserManager.isQuietModeEnabled()`](https://developer.android.com/reference/android/os/UserManager#isQuietModeEnabled(android.os.UserHandle)).

## Lock down any app to a device

Starting in Android 9, device owners and profile owners (of secondary users)
can lock *any* app to a device's screen by putting the app into lock task mode.
Previously, app developers had to [add support for lock task
mode](https://developer.android.com/work/cosu) in their apps. Android 9 also extends the lock task
APIs to profile owners of non-affiliated secondary users. Follow the steps below
to lock an app to the screen:

1. Call [`DevicePolicyManager.setLockTaskPackages()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setLockTaskPackages(android.content.ComponentName,%20java.lang.String%5B%5D)) to allowlist apps for lock task mode.
2. Call [`ActivityOptions.setLockTaskEnabled()`](https://developer.android.com/reference/android/app/ActivityOptions#setLockTaskEnabled(boolean)) to launch an allowlisted app into lock task mode.

To stop an app in lock task mode, remove the app from the lock task mode
allowlist using
[`DevicePolicyManager.setLockTaskPackages()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setLockTaskPackages(android.content.ComponentName,%20java.lang.String%5B%5D)).

#### Enable system UI features

When lock task mode is enabled, device owners and profile owners can enable
certain system UI features on the device by calling
[`DevicePolicyManager.setLockTaskFeatures()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setLockTaskFeatures(android.content.ComponentName,%20int)) and passing a
bit field of the following feature flags:

- [`LOCK_TASK_FEATURE_NONE`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_NONE)
- [`LOCK_TASK_FEATURE_SYSTEM_INFO`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_SYSTEM_INFO)
- [`LOCK_TASK_FEATURE_HOME`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_HOME)
- [`LOCK_TASK_FEATURE_NOTIFICATIONS`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_NOTIFICATIONS) can only be used in combination with `LOCK_TASK_FEATURE_HOME`.
- [`LOCK_TASK_FEATURE_KEYGUARD`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_KEYGUARD)
- [`LOCK_TASK_FEATURE_OVERVIEW`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_OVERVIEW) can only be used in combination with `LOCK_TASK_FEATURE_HOME`.
- [`LOCK_TASK_FEATURE_GLOBAL_ACTIONS`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_GLOBAL_ACTIONS)

You can call [`DevicePolicyManager.getLockTaskFeatures()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getLockTaskFeatures(android.content.ComponentName))
to get the list of features available on a device when lock task mode is
enabled. When a device exits lock task mode, it returns to the state mandated by
other device policies.

### Suppress error dialogs

In some environments, such as retail demonstrations or public information
displays, you might not want to show error dialogs to users. A device policy
controller (DPC) can suppress system error dialogs for crashed or unresponsive
apps by adding the
[`DISALLOW_SYSTEM_ERROR_DIALOGS`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_SYSTEM_ERROR_DIALOGS) user
restriction. This restriction affects all dialogs when applied by a device owner
but only the error dialogs shown in the primary or secondary user are suppressed
when the restriction is applied by profile owners. This restriction doesn't
affect work profiles.

In Android 9, apps running in [immersive full-screen
mode](https://developer.android.com/training/system-ui/immersive) don't show the reminder bubble when in
lock task mode. The reminder bubble is a panel shown to users (on first launch)
that explains how to exit the immersive mode.

## Support multiple users on dedicated devices

Android 9 introduces the concept of an **ephemeral user** for dedicated
devices (previously called [COSU](https://developer.android.com/work/cosu) devices). Ephemeral users are
short-term users intended for cases where multiple users share a single
dedicated device. This includes public user sessions on devices such as library
or hospitality check-in kiosks, as well as persistent sessions between a fixed
set of users on devices, for example, shift workers.

Ephemeral users should be created in the background. They are created as
secondary users on a device and are removed (along with associated apps and
data) when they are stopped, switched, or the device reboots. To create an
ephemeral user, device owners can:

1. Set the [`MAKE_USER_EPHEMERAL`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#MAKE_USER_EPHEMERAL) flag when calling [`DevicePolicyManager.createAndManageUser()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#createAndManageUser(android.content.ComponentName,%20java.lang.String,%20android.content.ComponentName,%20android.os.PersistableBundle,%20int)).
2. Call [`DevicePolicyManager.startUserInBackground()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#startUserInBackground(android.content.ComponentName,%20android.os.UserHandle)) to start the ephemeral user in the background.

Note, apps targeting Android 9 should catch
[`UserManager.UserOperationException`](https://developer.android.com/reference/android/os/UserManager.UserOperationException) when calling
`createAndManageUser()`. Call the exception's
[`getUserOperationResult()`](https://developer.android.com/reference/android/os/UserManager.UserOperationException#getUserOperationResult()) method to find out why the
user wasn't created.

### Receive event notifications

The [`DeviceAdminReceiver`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver) receives notifications for the
following events:

- [`onUserStarted()`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver#onUserStarted(android.content.Context,%20android.content.Intent,%20android.os.UserHandle)): Called when a user starts.
- [`onUserSwitched()`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver#onUserSwitched(android.content.Context,%20android.content.Intent,%20android.os.UserHandle)): Called when a [user switch](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#switchUser(android.content.ComponentName,%20android.os.UserHandle)) is completed.
- [`onUserStopped()`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver#onUserStopped(android.content.Context,%20android.content.Intent,%20android.os.UserHandle)): Called along with [`onUserRemoved()`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver#onUserRemoved(android.content.Context,%20android.content.Intent,%20android.os.UserHandle)) when a [user stops](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#stopUser(android.content.ComponentName,%20android.os.UserHandle)) or [logs
  out](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#logoutUser(android.content.ComponentName)).

### Display event messages to users

Device owners can configure the messages that are displayed to users when they
start and end their sessions:

- Use [`DevicePolicyManager.setStartUserSessionMessage()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setStartUserSessionMessage(android.content.ComponentName,%20java.lang.CharSequence)) to set the message that's displayed to a user when the user's session begins. To retrieve the message, call [`DevicePolicyManager.getStartUserSessionMessage()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getStartUserSessionMessage(android.content.ComponentName)).
- Use [`DevicePolicyManager.setEndUserSessionMessage()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setEndUserSessionMessage(android.content.ComponentName,%20java.lang.CharSequence)) to set the message that's displayed to the user when the user's session ends. To retrieve the message, call [`DevicePolicyManager.getEndUserSessionMessage()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getEndUserSessionMessage(android.content.ComponentName)).

### Log out and stop users

Device owners can use
[`DevicePolicyManager.setLogoutEnabled()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setLogoutEnabled(android.content.ComponentName,%20boolean)) to specify whether
logout is enabled for secondary users. To check if logout is enabled, call
[`DevicePolicyManager.isLogoutEnabled()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isLogoutEnabled()).

Profile owners of secondary users can call
[`DevicePolicyManager.logoutUser()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#logoutUser(android.content.ComponentName)) to stop the secondary user and
switch back to the primary user.

Device owners can use [`DevicePolicyManager.stopUser()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#stopUser(android.content.ComponentName,%20android.os.UserHandle)) to stop a
specified secondary user.

### Package caching

To streamline user provisioning on shared devices with a fixed set of users,
such as devices for shift workers, it's possible to cache packages that are
needed for multi-user sessions:

1. Call
   [`DevicePolicyManager.setKeepUninstalledPackages()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setKeepUninstalledPackages(android.content.ComponentName,%20java.util.List%3Cjava.lang.String%3E))
   to specify the list of packages to keep as APKs. To retrieve a list of these
   packages, call
   [`DevicePolicyManager.getKeepUninstalledPackages()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getKeepUninstalledPackages(android.content.ComponentName)).

2. Call [`DevicePolicyManager.installExistingPackage()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#installExistingPackage(android.content.ComponentName,%20java.lang.String))
   to install a package that has been kept after removal via
   [`setKeepUninstalledPackages()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setKeepUninstalledPackages(android.content.ComponentName,%20java.util.List%3Cjava.lang.String%3E)).

| **Note:** If a profile owner calls [`DevicePolicyManager.installExistingPackage()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#installExistingPackage(android.content.ComponentName,%20java.lang.String)), the user must be affiliated with the device. To check if a [user is
| affiliated](https://developer.android.com/work/dpc/work-profile-on-managed-device#affiliated-users) with the device, use [`DevicePolicyManager.isAffiliatedUser()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isAffiliatedUser()).

### Additional methods and constants

Android 9 also includes the following methods and constants to further support
user sessions on shared devices:

- [`DevicePolicyManager.getSecondaryUsers()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getSecondaryUsers(android.content.ComponentName)) gets a list of all secondary users on a device.
- [`DISALLOW_USER_SWITCH`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_USER_SWITCH) is a user restriction you can enable by calling [`DevicePolicyManager.addUserRestriction()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#addUserRestriction(android.content.ComponentName,%20java.lang.String)) to block user switching.
- [`LEAVE_ALL_SYSTEM_APPS_ENABLED`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LEAVE_ALL_SYSTEM_APPS_ENABLED) is a flag available for [`DevicePolicyManager.createAndManageUser()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#createAndManageUser(android.content.ComponentName,%20java.lang.String,%20android.content.ComponentName,%20android.os.PersistableBundle,%20int)). When set, system apps aren't disabled during user provisioning.
- [`UserManager.UserOperationException`](https://developer.android.com/reference/android/os/UserManager.UserOperationException) is thrown by `DevicePolicyManager.createAndManageUser()` when a user can't be created---the exception contains the reason for the failure.

## Clear package data and remove accounts

Device owners and profile owners can call
[`clearApplicationUserData()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#clearApplicationUserData(android.content.ComponentName,%20java.lang.String,%20java.util.concurrent.Executor,%20android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener)) to clear the user data
for a given package. To remove an account from the
[`AccountManager`](https://developer.android.com/reference/android/accounts/AccountManager), device and profile owners can call
[`removeAccount()`](https://developer.android.com/reference/android/accounts/AccountManager#removeAccount(android.accounts.Account,%20android.app.Activity,%20android.accounts.AccountManagerCallback%3Candroid.os.Bundle%3E,%20android.os.Handler)).

## User restrictions and increased control over settings

Android 9 introduces a set of user restrictions for DPCs, as well as the
ability to configure APNs, time and timezone, and system settings on a device.

### Configure APNs

Device owners can use the following methods in the
[`DevicePolicyManager`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager) class to configure APNs on a
device:

- [`addOverrideApn()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#addOverrideApn(android.content.ComponentName,%20android.telephony.data.ApnSetting))
- [`updateOverrideApn()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#updateOverrideApn(android.content.ComponentName,%20int,%20android.telephony.data.ApnSetting))
- [`removeOverrideApn()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#removeOverrideApn(android.content.ComponentName,%20int))
- [`getOverrideApns()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getOverrideApns(android.content.ComponentName))
- [`setOverrideApnEnabled()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setOverrideApnsEnabled(android.content.ComponentName,%20boolean))
- [`isOverrideApnEnabled()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isOverrideApnEnabled(android.content.ComponentName))

### Configure time and timezone

Device owners can use the following methods in the
[`DevicePolicyManager`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager) class to set the time and timezone
on a device:

- [`setTime()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setTime(android.content.ComponentName,%20long))
- [`setTimeZone()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setTimeZone(android.content.ComponentName,%20java.lang.String))

### Enforce user restrictions on important settings

Android 9 adds user restrictions to disable system features and settings. To
add a restriction, call
[`DevicePolicyManager.addUserRestriction()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#addUserRestriction(android.content.ComponentName,%20java.lang.String)) with one of the
following `UserManager` constants:

- [`DISALLOW_AIRPLANE_MODE`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_AIRPLANE_MODE)
- [`DISALLOW_AMBIENT_DISPLAY`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_AMBIENT_DISPLAY)
- [`DISALLOW_CONFIG_BRIGHTNESS`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_CONFIG_BRIGHTNESS)
- [`DISALLOW_CONFIG_DATE_TIME`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_CONFIG_DATE_TIME)
- [`DISALLOW_CONFIG_LOCATION`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_CONFIG_LOCATION)
- [`DISALLOW_CONFIG_SCREEN_TIMEOUT`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_CONFIG_SCREEN_TIMEOUT)
- [`DISALLOW_PRINTING`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_PRINTING)

If [`DISALLOW_CONFIG_BRIGHTNESS`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_CONFIG_BRIGHTNESS) and
[`DISALLOW_CONFIG_SCREEN_TIMEOUT`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_CONFIG_SCREEN_TIMEOUT) are enforced
on a device, device owners can still set the [screen
brightness](https://developer.android.com/reference/android/provider/Settings.System#SCREEN_BRIGHTNESS), [screen brightness
mode](https://developer.android.com/reference/android/provider/Settings.System#SCREEN_BRIGHTNESS_MODE), and [screen timeout](https://developer.android.com/reference/android/provider/Settings.System#SCREEN_OFF_TIMEOUT) settings
on the device using the API
[`DevicePolicyManager.setSystemSetting()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setSystemSetting(android.content.ComponentName,%20java.lang.String,%20java.lang.String)).

### Metered data

Device owners and profile owners can prevent apps from using a device's
metered-data networks. A network is considered metered when when the user is
sensitive to heavy data usage because of cost, data limits, or battery and
performance issues. To prevent apps from using metered networks, call
[`DevicePolicyManager.setMeteredDataDisabledPackages()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setMeteredDataDisabledPackages(android.content.ComponentName,%20java.util.List%3Cjava.lang.String%3E))
passing a list of package names. To retrieve the currently restricted apps, call
[`DevicePolicyManager.getMeteredDataDisabledPackages()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getMeteredDataDisabledPackages(android.content.ComponentName)).

To learn more about metered data in Android, read [Optimizing Network Data
Usage](https://developer.android.com/training/basics/network-ops/data-saver).

## Migrate DPCs

Device policy controllers (DPCs) can transfer their ownership of a device or
work profile to another DPC. You might transfer ownership to move some features
to the [Android Management
API](https://developers.google.com/android/management/), to migrate devices from
your legacy DPC, or to help IT admins migrate to your EMM. Because you're just
changing the DPC ownership, you can't use this feature to change the type of
management, for example, migrating from a managed device to a work profile or
vice-versa.

You can use the [device admin policies](https://developer.android.com/work/device-admin#manifest) XML resource to
indicate that this version of your DPC supports migration. A target DPC
indicates it can receive ownership by including a element named
`<support-transfer-ownership>`. The example below shows how you might do this in
your DPC's device admin XML file:  

    <device-admin xmlns:android="http://schemas.android.com/apk/res/android">
        <support-transfer-ownership />
        <uses-policies>
            <limit-password />
            <watch-login />
            <reset-password />
        </uses-policies>
    </device-admin>

DPCs that want to migrate ownership to new DPC app can check if a target DPC's
version supports migration by calling the `DeviceAdminInfo` method
[`supportsTransferOwnership()`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#supportsTransferOwnership()). Before transferring
ownership, it's the source DPC's responsibility to verify the target DPC by
comparing app signatures. The [`PackageManager`](https://developer.android.com/reference/android/content/pm/PackageManager) class includes
methods to work with code-sign signatures.

Android maintains the source DPC's system and user policies through an ownership
transfer---DPCs don't need to migrate these. A source DPC can pass custom data to
the target DPC using key-value pairs in a `PersistableBundle`. After a
successful transfer, the target DPC can retrieve this data by calling
[`DevicePolicyManager.getTransferOwnershipBundle()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getTransferOwnershipBundle()).

The steps to transfer ownership of a managed device or a work profile are the
same:

1. The source DPC checks that the target DPC's version supports migration and confirms that the target DPC's app signature matches an expected value.
2. The source DPC calls [`transferOwnership()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#transferOwnership(android.content.ComponentName,%20android.content.ComponentName,%20android.os.PersistableBundle)) to start the transfer.
3. The system makes the target DPC the [active admin](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getActiveAdmins()) and sets it as the owner of the managed device or work profile.
4. The target DPC receives the callback [`onTransferOwnershipComplete()`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver#onTransferOwnershipComplete(android.content.Context,%20android.os.PersistableBundle)) and can configure itself using values from the `bundle` argument.
5. If something goes wrong with the transfer, the system reverts ownership to the source DPC. If your source DPC needs to confirm that the ownership transfer succeeded, call [`isAdminActive()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isAdminActive(android.content.ComponentName)) to check that the source DPC is no longer the active admin.

All apps running in the work profile receive the
[`ACTION_PROFILE_OWNER_CHANGED`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#ACTION_PROFILE_OWNER_CHANGED) broadcast when
the profile owner changes. Apps running on a managed device receive the
[`ACTION_DEVICE_OWNER_CHANGED`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#ACTION_DEVICE_OWNER_CHANGED) broadcast when the
device owner changes.

#### Work profiles on fully managed devices

Transferring two instances of a DPC running as device owner and profile owner
happens in two stages. When the personal profile and work profile [are
affiliated](https://developer.android.com/work/dpc/work-profile-on-managed-device#affiliated-users), complete the transfer in the following order:

1. First, transfer ownership of the work profile.
2. Wait for the `DeviceAdminReceiver` callback [`onTransferAffiliatedProfileOwnershipComplete()`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver#onTransferAffiliatedProfileOwnershipComplete(android.content.Context,%20android.os.UserHandle)) to confirm that the work profile was transferred to the target DPC.
3. Finally, transfer ownership of the managed device to the target DPC.

## Postpone Over-the-air (OTA) updates

| **Warning:** Postponing OTA updates can prevent devices from receiving critical updates.

Device owners can postpone OTA system updates to devices for up to 90 days to
freeze the OS version running on these devices over critical periods (such as
holidays). The system enforces a mandatory 60-day buffer after any defined
freeze period to prevent freezing the device indefinitely.

During a freeze period:

- Devices don't receive any notifications about pending OTA updates.
- Devices don't install any OTA updates to the OS.
- Device users aren't able to manually check for OTA updates in Settings.

To set a freeze period, call
[`SystemUpdatePolicy.setFreezePeriods()`](https://developer.android.com/reference/android/app/admin/SystemUpdatePolicy#setFreezePeriods(java.util.List%3Candroid.util.Pair%3Cjava.lang.Integer,%20java.lang.Integer%3E%3E)). Because the freeze
period repeats annually, the start and end dates of the period are represented
by integers counting the number of days since year start. The start day must
begin at least 60 days after the end of any previous freeze period. Device
owners can call [`SystemUpdatePolicy.getFreezePeriods()`](https://developer.android.com/reference/android/app/admin/SystemUpdatePolicy#getFreezePeriods()) to
get a list of freeze periods previously set on the system update policy object.
[`DevicePolicyManager.getSystemUpdatePolicy()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getSystemUpdatePolicy()) has been
updated to return any freeze periods set by the device owner.

## Restrict sharing into a work profile

Profile owners can prevent users from sharing personal data into a work profile
on the device by adding the user restriction
[`DISALLOW_SHARE_INTO_MANAGED_PROFILE`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_SHARE_INTO_MANAGED_PROFILE).
This restriction prevents the following intent handling and sharing:

- Personal profile apps sharing data and files with work profile apps.
- Work profile apps picking items from the personal profile---for example, pictures or files.

After setting this restriction, your DPC can still permit cross-profile Activity
intents by calling
[`addCrossProfileIntentFilter()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#addCrossProfileIntentFilter(android.content.ComponentName,%20android.content.IntentFilter,%20int)).

## Hardware-secured keys and machine certificates

Android 9 adds APIs to help you work with keys and certificates that you can
combine to securely identify devices. A DPC running in profile owner or device
owner modes, or a [delegated certificate installer](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#DELEGATION_CERT_INSTALL), can
complete the following tasks:

- Generate keys and certificates in the secure hardware (such as a trusted execution environment (TEE) or Secure Element (SE)) of the Android device. The generated keys never leave the secure hardware and can be used from the [Android
  KeyChain](https://developer.android.com/reference/android/security/KeyChain). Call [`DevicePolicyManager.generateKeyPair()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#generateKeyPair(android.content.ComponentName,%20java.lang.String,%20android.security.keystore.KeyGenParameterSpec,%20int)) supplying the algorithm (see [`KeyPairGenerator`](https://developer.android.com/reference/java/security/KeyPairGenerator)) and any hardware IDs you want attested, such as the serial number or IMEI. To learn more about secure hardware changes, see the [Android 9 Security
  enhancements](https://developer.android.com/about/versions/pie/android-9.0#security).
- Associate a certificate with an existing device-generated key. Call [`DevicePolicyManager.setKeyPairCertificate()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setKeyPairCertificate(android.content.ComponentName,%20java.lang.String,%20java.util.List%3Cjava.security.cert.Certificate%3E,%20boolean)) supplying the alias of the existing key and the certificate chain---starting with the leaf certificate and including the chain of trust in order.
- Confirm that the secure hardware protects the key before using it. To check which mechanisms protect the key, follow the steps in [Key
  Attestation](https://developer.android.com/training/articles/security-key-attestation).
- Device owners and delegated certificate installers can receive a signed statement of the devices' hardware IDs with Android system versions. Call [`DevicePolicyManager.generateKeyPair()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#generateKeyPair(android.content.ComponentName,%20java.lang.String,%20android.security.keystore.KeyGenParameterSpec,%20int)) passing one or more of [`ID_TYPE_BASE_INFO`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#ID_TYPE_BASE_INFO), [`ID_TYPE_SERIAL`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#ID_TYPE_SERIAL), [`ID_TYPE_IMEI`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#ID_TYPE_IMEI), or [`ID_TYPE_MEID`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#ID_TYPE_MEID) in the `idAttestationFlags` argument. The returned certificate includes the hardware IDs in the attestation record. If you don't want the hardware IDs included, pass `0`. Profile owners can only receive manufacturer information (by passing `ID_TYPE_BASE_INFO`). To check that the device can attest IDs, call [`isDeviceIdAttestationSupported()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isDeviceIdAttestationSupported()).
- Prevent device users from misusing enterprise keys (in non-enterprise tasks) by making the key certificates unselectable. The system doesn't include unselectable certificates in the picker panel. In your [`DeviceAdminReceiver.onChoosePrivateKeyAlias()`](https://developer.android.com/reference/android/app/admin/DeviceAdminReceiver#onChoosePrivateKeyAlias(android.content.Context,%20android.content.Intent,%20int,%20android.net.Uri,%20java.lang.String)) callback method, return the alias to your enterprise key so that the system automatically selects the certificate on behalf of the user. To make a key unselectable, call the following `DevicePolicyManager` methods:
  - [`setKeyPairCertificate()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setKeyPairCertificate(android.content.ComponentName,%20java.lang.String,%20java.util.List%3Cjava.security.cert.Certificate%3E,%20boolean)) and pass `false` for the `isUserSelectable` argument.
  - [`installKeyPair (ComponentName, PrivateKey, Certificate[], String, int)`](https://developer.android.com/work/versions/reference/android/app/admin/DevicePolicyManager#installKeyPair(android.content.ComponentName,%20java.security.PrivateKey,%20java.security.cert.Certificate%5B%5D,%20java.lang.String,%20boolean,%20int)) and omit [`INSTALLKEY_SET_USER_SELECTABLE`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#INSTALLKEY_SET_USER_SELECTABLE) from the `flags` argument.

By combining these APIs, enterprises can securely identify devices and confirm
their integrity before providing access:

1. The Android device generates a new private key in the secure hardware. Because the private key never leaves the secure hardware, it remains secret.
2. The device uses the key to create and send a certificate signing request (CSR) to the server. The CSR includes the attestation record containing the device IDs.
3. The server validates the certificate chain (rooted to a Google certificate) and extracts the device metadata from the attestation record.
4. The server confirms that the secure hardware protects the private key and that the device IDs match the enterprise's records. The server can also check that the Android system and patch versions meet any requirements.
5. The server generates a certificate from the CSR and sends the certificate to the device.
6. The device pairs the certificate with the private key (that's remained in the secure hardware) enabling apps to connect to enterprise services.

## More security APIs, features, and changes

### IDs for security logs and network logs

Android 9 includes IDs in security and network activity logs. The numeric ID
monotonically increases for each event, making it easier for IT admins to spot
gaps in their logs. Because security logs and network logs are separate
collections, the system maintains separate ID values.

Call [`SecurityEvent.getId()`](https://developer.android.com/reference/android/app/admin/SecurityLog.SecurityEvent#getId()),
[`DnsEvent.getId()`](https://developer.android.com/reference/android/app/admin/NetworkEvent#getId()), or
[`ConnectEvent.getId()`](https://developer.android.com/reference/android/app/admin/NetworkEvent#getId()) to get the ID value. The system
resets the ID whenever a DPC enables logging or when the device restarts.
Security logs fetched by calling
[`DevicePolicyManager.retrievePreRebootSecurityLogs()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#retrievePreRebootSecurityLogs(android.content.ComponentName))
don't include these IDs.

### Security logging

Security logging assigns each `SecurityEvent` a log level. To get the log level,
call [`getLogLevel()`](https://developer.android.com/reference/android/app/admin/SecurityLog.SecurityEvent#getLogLevel()). This method returns a log level value that
can be one of: [`LEVEL_INFO`](https://developer.android.com/reference/android/app/admin/SecurityLog#LEVEL_INFO), [`LEVEL_WARNING`](https://developer.android.com/reference/android/app/admin/SecurityLog#LEVEL_WARNING), or
[`LEVEL_ERROR`](https://developer.android.com/reference/android/app/admin/SecurityLog#LEVEL_ERROR).

Android 9 logs the events listed in the table below into [security
logs](https://developer.android.com/work/dpc/security#log_enterprise_device_activity). To check an event's tag, call [`getTag()`](https://developer.android.com/reference/android/app/admin/SecurityLog.SecurityEvent#getTag()). To
retrieve the event data, call [`getData()`](https://developer.android.com/reference/android/app/admin/SecurityLog.SecurityEvent#getData()).

|                                                                       Tag                                                                        |                                    Event description                                     |
|--------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
| [`TAG_CERT_AUTHORITY_INSTALLED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_CERT_AUTHORITY_INSTALLED)             | An attempt to install a new root certificate into the system's credential storage.       |
| [`TAG_CERT_AUTHORITY_REMOVED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_CERT_AUTHORITY_REMOVED)                 | An attempt to remove a root certificate from the system's credential storage.            |
| [`TAG_CERT_VALIDATION_FAILURE`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_CERT_VALIDATION_FAILURE)               | A Wi-Fi certificate failed a validation check during connection.                         |
| [`TAG_CRYPTO_SELF_TEST_COMPLETED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_CRYPTO_SELF_TEST_COMPLETED)         | The system completed the cryptographic self test.                                        |
| [`TAG_KEYGUARD_DISABLED_FEATURES_SET`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_KEYGUARD_DISABLED_FEATURES_SET) | An admin app disabled features of a device or work profile lock screen.                  |
| [`TAG_KEY_DESTRUCTION`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_KEY_DESTRUCTION)                               | An attempt to delete a cryptographic key.                                                |
| [`TAG_KEY_GENERATED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_KEY_GENERATED)                                   | An attempt to generate a new cryptographic key.                                          |
| [`TAG_KEY_IMPORT`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_KEY_IMPORT)                                         | An attempt to import a new cryptographic key.                                            |
| [`TAG_KEY_INTEGRITY_VIOLATION`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_KEY_INTEGRITY_VIOLATION)               | Android detected a damaged encryption or authentication key.                             |
| [`TAG_LOGGING_STARTED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_LOGGING_STARTED)                               | Security logging started recording.                                                      |
| [`TAG_LOGGING_STOPPED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_LOGGING_STOPPED)                               | Security logging stopped recording.                                                      |
| [`TAG_LOG_BUFFER_SIZE_CRITICAL`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_LOG_BUFFER_SIZE_CRITICAL)             | The security log buffer reached 90% of its capacity.                                     |
| [`TAG_MAX_PASSWORD_ATTEMPTS_SET`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_MAX_PASSWORD_ATTEMPTS_SET)           | An admin app set the number of allowed incorrect-password attempts.                      |
| [`TAG_MAX_SCREEN_LOCK_TIMEOUT_SET`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_MAX_SCREEN_LOCK_TIMEOUT_SET)       | An admin app set a maximum screen-lock timeout.                                          |
| [`TAG_MEDIA_MOUNT`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_MEDIA_MOUNT)                                       | The device mounted removable storage media.                                              |
| [`TAG_MEDIA_UNMOUNT`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_MEDIA_UNMOUNT)                                   | The device unmounted removable storage media.                                            |
| [`TAG_OS_SHUTDOWN`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_OS_SHUTDOWN)                                       | The Android system shut down.                                                            |
| [`TAG_OS_STARTUP`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_OS_STARTUP)                                         | The Android system started up.                                                           |
| [`TAG_PASSWORD_COMPLEXITY_SET`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_PASSWORD_COMPLEXITY_SET)               | An admin app set password complexity requirements.                                       |
| [`TAG_PASSWORD_EXPIRATION_SET`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_PASSWORD_EXPIRATION_SET)               | An admin app set a password expiry duration.                                             |
| [`TAG_PASSWORD_HISTORY_LENGTH_SET`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_PASSWORD_HISTORY_LENGTH_SET)       | An admin app set a password history length, preventing users from reusing old passwords. |
| [`TAG_REMOTE_LOCK`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_REMOTE_LOCK)                                       | An admin app locked the device or work profile.                                          |
| [`TAG_USER_RESTRICTION_ADDED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_USER_RESTRICTION_ADDED)                 | An admin app set a user restriction.                                                     |
| [`TAG_USER_RESTRICTION_REMOVED`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_USER_RESTRICTION_REMOVED)             | An admin app removed a user restriction.                                                 |
| [`TAG_WIPE_FAILURE`](https://developer.android.com/reference/android/app/admin/SecurityLog#TAG_WIPE_FAILURE)                                     | An attempt to wipe a device or work profile failed.                                      |

### Work profile lock screen challenge

Beginning in Android 9, profile owners can require users to set a separate lock
screen challenge for their work profile using the
[`DISALLOW_UNIFIED_PASSWORD`](https://developer.android.com/reference/android/os/UserManager#DISALLOW_UNIFIED_PASSWORD) user restriction. To
check whether a user has the same lock screen challenge set for their device and
work profile, call
[`DevicePolicyManager.isUsingUnifiedPassword()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isUsingUnifiedPassword(android.content.ComponentName)).

If a device has a separate work profile lock screen,
[`DevicePolicyManager.setMaximumTimeToLock()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setMaximumTimeToLock(android.content.ComponentName,%20long)) only sets a
lock screen timeout for the work profile instead of for the entire device.

### Developer tools access

To help keep work data in the work profile, the Android Debug Bridge (adb) tool
can't access directories and files in the work profile.

### Support for more biometric options

Android 9 adds fine-grained control over biometric hardware authentication in a
work profile's lock screen. Call the existing
[`DevicePolicyManager.setKeyguardDisabledFeatures()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setKeyguardDisabledFeatures(android.content.ComponentName,%20int))
method with [`KEYGUARD_DISABLE_FACE`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#KEYGUARD_DISABLE_FACE) and
[`KEYGUARD_DISABLE_IRIS`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#KEYGUARD_DISABLE_IRIS).
To disable all biometric authentication methods provided by the device, add [`KEYGUARD_DISABLE_BIOMETRICS`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#KEYGUARD_DISABLE_BIOMETRICS).

## Deprecation of device admin policies

Android 9 marks the policies listed below as deprecated for DPCs using [device
admin](https://developer.android.com/work/device-admin). The policies continue to function
in Android 9 as they have done previously. Starting with the Android 10 release,
the same policies will throw a SecurityException when invoked by a device admin.

- [`USES_POLICY_DISABLE_CAMERA`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA)
- [`USES_POLICY_DISABLE_KEYGUARD_FEATURES`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES)
- [`USES_POLICY_EXPIRE_PASSWORD`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD)
- [`USES_POLICY_LIMIT_PASSWORD`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD)

Some applications use device admin for consumer device administration. For
example, locking and wiping a lost device. The following policies will continue
to be available to enable this:

- [`USES_POLICY_WIPE_DATA`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_WIPE_DATA)
- [`USES_POLICY_FORCE_LOCK`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_FORCE_LOCK)
- [`USES_POLICY_RESET_PASSWORD`](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_RESET_PASSWORD)

For more information about these changes, read [Device admin
deprecation](https://developers.google.com/android/work/device-admin-deprecation).

## Streamlined QR-code enrollment

### Built-in QR library

Android 9 comes bundled with a QR library to streamline QR-code device
provisioning. IT admins no longer have to manually enter Wi-Fi details to set up
a device. Instead, with Android 9 it's possible to include these Wi-Fi details
within a QR code. When an IT admin scans the QR code with a company-owned
device, the device automatically connects to Wi-Fi and enters the provisioning
process without any additional manual input.

The QR-code provisioning method supports the following provisioning extras to
specify Wi-Fi details:

- [`EXTRA_PROVISIONING_WIFI_HIDDEN`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_HIDDEN)
- [`EXTRA_PROVISIONING_WIFI_PAC_URL`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_PAC_URL)
- [`EXTRA_PROVISIONING_WIFI_PASSWORD`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_PASSWORD)
- [`EXTRA_PROVISIONING_WIFI_PROXY_BYPASS`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_PROXY_BYPASS)
- [`EXTRA_PROVISIONING_WIFI_PROXY_HOST`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_PROXY_HOST)
- [`EXTRA_PROVISIONING_WIFI_PROXY_PORT`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_PROXY_PORT)
- [`EXTRA_PROVISIONING_WIFI_SECURITY_TYPE`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_SECURITY_TYPE)
- [`EXTRA_PROVISIONING_WIFI_SSID`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_WIFI_SSID)

### Set date and timezone using provisioning extras

The QR-code provisioning method supports provisioning extras to set the time and
timezone on a device:

- [`EXTRA_PROVISIONING_TIME_ZONE`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_TIME_ZONE)
- [`EXTRA_PROVISIONING_LOCAL_TIME`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_LOCAL_TIME)
- [`EXTRA_PROVISIONING_LOCALE`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#EXTRA_PROVISIONING_LOCALE)

## Wiping data options

Device admins can show a personalized message to users when removing a work
profile or secondary user. The message helps device users understand that their
IT admin removed the work profile or secondary user. Call
[`wipeData(int, CharSequence)`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#wipeData(int,%20java.lang.CharSequence)) and supply a short
explanatory message. When called by the primary user or device owner, the system
doesn't show a message and begins a factory reset of the device.

To remove subscription data from an embedded eUICC SIM, call
[`wipeData()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#wipeData(int,%20java.lang.CharSequence)) and include [`WIPE_EUICC`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#WIPE_EUICC) in the `flags`
argument.

## Methods for affiliated profile owners

The following methods are available to [affiliated profile](https://developer.android.com/work/dpc/work-profile-on-managed-device#affiliated-users)
owners:

- [`DevicePolicyManager.setKeyguardDisabled()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setKeyguardDisabled(android.content.ComponentName,%20boolean))
- [`DevicePolicyManager.setStatusBarDisabled()`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setStatusBarDisabled(android.content.ComponentName,%20boolean))
- [`PackageInstaller.createSession()`](https://developer.android.com/reference/android/content/pm/PackageInstaller#createSession(android.content.pm.PackageInstaller.SessionParams))