1page.title=Set up Single-Purpose Devices 2page.tags=work, cosu 3page.keywords=cosu, work 4page.metaDescription=Learn how to develop single-use solutions for Android devices. 5page.image=images/work/cards/briefcase_600px.png 6 7@jd:body 8 9<div id="qv-wrapper"> 10 <div id="qv"> 11 <h2>In this document</h2> 12 <ol> 13 <li><a href="#locktask">How to use LockTask mode</a></li> 14 <li><a href="#cosu-solutions">Build COSU solutions</a></li> 15 <li><a href="#create-dpc">Create your own DPC app</a></li> 16 </ol> 17 </div> 18</div> 19 20<p> 21As an IT administrator, you can configure Android 6.0 Marshmallow and later 22devices as <em>corporate-owned, single-use (COSU)</em> devices. These are Android 23devices used for a single purpose, such as digital signage, ticket printing, 24point of sale, or inventory management. To use Android devices as COSU devices, 25you need to develop Android apps that your customers can manage. 26</p> 27 28<p> 29Your customers can configure COSU devices: 30</p> 31<ul> 32<li> 33To lock a single application to the screen, and hide the 34<strong>Home</strong> and <strong>Recents</strong> buttons to prevent users 35from escaping the app. 36</li> 37 38<li> 39To allow multiple applications to appear on the screen, such as a library kiosk 40with a catalog app and web browser. 41</li> 42</ul> 43 44<h2 id="pinning"> 45App pinning vs. lock task mode 46</h2> 47 48<p>Android 5.0 Lollipop introduced two new ways to configure Android devices 49for a single purpose: 50</p> 51 52<ul> 53<li> 54With app pinning, the device user can temporarily pin specific apps to the 55screen. 56</li> 57 58<li> 59With lock task mode, a user can’t escape the app and the Home and Recents 60buttons are hidden. Additionally, lock task mode gives the IT administrator 61a more robust way to manage COSU devices, as discussed below. 62</li> 63</ul> 64 65<p> 66This graphic compares the features of app pinning and lock task mode: 67</p> 68 69<img src="{@docRoot}images/work/cosu-pinning_vs_locktaskmode.png" 70width="640" srcset="{@docRoot}images/work/cosu-pinning_vs_locktaskmode.png 1x, 71{@docRoot}images/work/cosu-pinning_vs_locktaskmode_2x.png 2x" /> 72 73 <p class="img-caption"> 74 <strong>Figure 1.</strong> Comparing the features of app pinning in Lollipop 75 vs. Lock task mode in Marshmallow and later 76 </p> 77 78<p> 79In Lollipop, you can pin a single application to cover the full screen, but 80only apps whitelisted by the device policy controller (DPC) can be locked. 81</p> 82 83<h2 id="locktask"> 84 How to use LockTask mode 85</h2> 86 87<p> 88 To use LockTask mode, and the APIs that manage COSU devices, there must be 89 a device owner application installed on the device. Device owners are a 90 type of device policy controller (DPC) that manages the whole device. For 91 more information about DPCs, see the 92 <a class="external-link" href="https://developers.google.com/android/work/overview">EMM Developer’s Overview</a>. 93</p> 94 95<p> 96If you’re creating a new COSU app, we recommend you develop it for 97Marshmallow or later, which includes the following COSU features: 98</p> 99 100<ul> 101<li> 102Controls system updates 103</li> 104 105<li> 106Sets status and menu bar visibility 107</li> 108 109<li> 110Disables screen lock and sleep functions 111</li> 112 113<li> 114Permits switching between apps while staying in lock task mode 115</li> 116 117<li> 118Prevents restarting in safe mode 119</li> 120</ul> 121 122<p class="note"> 123 <strong>Note:</strong> If you develop COSU features targeted for 124 Marshmallow devices, your app can still be compatible with prior 125 versions of Android. 126</p> 127 128<p> 129Additional COSU management features launched with Marshmallow make it easier to 130develop and deploy Android devices as a single-use device. If you want to 131enforce server-side managed configurations or server-side profile policy controls, 132you need to use an EMM or make your application a DPC. Follow the instructions 133below as you create your application. 134</p> 135 136<h2 id="cosu-solutions"> 137 Build COSU solutions 138</h2> 139 140<p> 141 There are two different ways to manage COSU devices: 142</p> 143 144<ul> 145<li> 146<strong>Use a third-party enterprise mobility management (EMM) 147solution</strong>: Using an EMM, all you need to do is set up lock task mode. 148For instructions, skip to the next section, 149<a href="#emm-solutions">Solutions managed by a third-party EMM</a>. 150</li> 151 152<li> 153<strong>Advanced setup—Create your own DPC app</strong>: This requires 154more work and is intended for an advanced developer audience. With this 155option, you’ll need to set up the device so that you can manage it, set 156up APIs, and set up a DPC app and test it. For instructions, skip to 157<a href="#create-dpc">Create your own DPC app</a>. 158</li> 159</ul> 160 161<h2 id="emm-solutions"> 162Solutions managed by a third-party EMM 163</h2> 164 165<p> 166In this section, you’ll need to do a small amount of development to 167have your device work with a third-party EMM. 168</p> 169 170<h3 id="use-smartlocktask"> 171Using startLockTask() 172</h3> 173 174<p> 175If you need to add COSU functionality to an existing app, make sure that 176the customer’s EMM supports {@link android.R.attr#lockTaskMode}. 177</p> 178 179<ul> 180<li> 181The device owner must include your app’s package(s) in 182{@link android.app.admin.DevicePolicyManager#setLockTaskPackages setLockTaskPackages}</li> 183<ul> 184<li> 185Sets the packages that can enter into lock task mode 186</li> 187<li> 188Needs to be set by the EMM 189</li> 190<li> 191You can call {@link android.app.admin.DevicePolicyManager#isLockTaskPermitted isLockTaskPermitted} 192to verify that your package has been whitelisted by 193{@link android.app.admin.DevicePolicyManager#setLockTaskPackages setLockTaskPackages}. 194</li> 195</ul> 196 197<li> 198Your activity calls {@link android.app.Activity#startLockTask()} 199</li> 200<ul> 201<li> 202Requests to lock the user into the current task 203</li> 204<li> 205Prevents launching other apps, settings, and the <strong>Home</strong> 206button 207</li> 208</ul> 209 210<li> 211To exit, your activity must call {@link android.app.Activity#stopLockTask()} 212</li> 213<ul> 214<li> 215Can only be called on an activity that’s previously called 216 {@link android.app.Activity#startLockTask()} 217</li> 218<li> 219Should be called when the app is user-facing between {@link android.app.Activity#onResume()} 220and {@link android.app.Activity#onPause()} 221</li> 222</ul> 223</ul> 224 225<p> 226Starting from Marshmallow, if your app is whitelisted by an EMM using {@link 227android.app.admin.DevicePolicyManager#setLockTaskPackages setLockTaskPackages}, 228your activities can automatically start lock task mode when the app is 229launched. 230</p> 231 232<h3 id="locktaskmode-attribute"> 233Set the lockTaskMode attribute 234</h3> 235 236<p> 237 The {@link android.R.attr#lockTaskMode} attribute allows you to define 238 your app’s lock task mode behavior in the AndroidManifest.xml file: 239</p> 240 241<ul> 242<li> 243If you set {@link android.R.attr#lockTaskMode} to <code>if_whitelisted</code>, 244you don’t need to call {@link android.app.Activity#startLockTask()}, and the 245app automatically enters into lock task mode. 246</li> 247 248<li> 249System apps and privileged apps can also set {@link android.R.attr#lockTaskMode} 250to always. This setting causes tasks (rooted at your activity) to always 251launch into lock task mode. Non-privileged apps are treated as normal. 252</li> 253 254<li> 255The default value of the {@link android.R.attr#lockTaskMode} attribute is 256normal. When this attribute is set to normal, tasks don’t launch into 257{@link android.R.attr#lockTaskMode}, unless {@link android.app.Activity#startLockTask()} 258is called. To call {@link android.app.Activity#startLockTask()}, 259applications still need to be whitelisted using 260{@link android.app.admin.DevicePolicyManager#setLockTaskPackages setLockTaskPackages}, 261otherwise, the user sees a dialog to approve entering pinned mode. 262</li> 263</ul> 264 265<p>To have your activity <em>automatically</em> enter {@link android.R.attr#lockTaskMode}, 266change the value of this attribute to <code>if_whitelisted</code>. 267Doing so causes your app to behave in this manner: 268</p> 269 270<ul> 271<li> 272If your app isn’t whitelisted for {@link android.R.attr#lockTaskMode}, 273it behaves as normal. 274</li> 275 276<li> 277If your app is a system or privileged app, and it’s whitelisted, 278{@link android.R.attr#lockTaskMode} automatically starts when the app is 279launched. 280</li> 281</ul> 282 283<p> 284Example XML as follows: 285</p> 286 287 <pre><activity android:name=".MainActivity" android:lockTaskMode="if_whitelisted"></pre> 288 289<p> 290Given either of these options, you still need to create a mechanism for 291calling {@link android.app.Activity#stopLockTask()} so that users can 292exit {@link android.R.attr#lockTaskMode}. 293</p> 294 295<h2 id="create-dpc"> 296 Advanced setup—Create your own DPC app 297</h2> 298 299<p> 300To manage applications in COSU, you need a DPC running as device 301owner to set several policies on the device. 302</p> 303 304<p class="note"> 305<strong>Note:</strong> This setup is advanced, and requires 306a thorough understanding of the EMM concepts described in the 307<a class="external-link" href="https://developers.google.com/android/work/prov-devices#implementation_considerations_for_device_owner_mode">EMM developer overview</a>. 308For more information about building a DPC, see 309<a class="external-link" 310href="https://developers.google.com/android/work/prov-devices">Provision Customer Devices</a>. 311</p> 312 313<p> 314To create a DPC app that can manage COSU device configuration, 315the DPC needs to: 316</p> 317 318<ol> 319<li> 320Provision the device into device owner mode. We recommend that 321you support provisioning with near field communication (NFC) bump. 322For more information, see 323<a class="external-link" href="https://developers.google.com/android/work/prov-devices#nfc_method" 324>Device Owner Provisioning via NFC</a>. 325</li> 326 327<li> 328Use the following APIs: 329<ul> 330<li> 331Keep devices from locking with the keyguard using 332{@link android.app.admin.DevicePolicyManager#setKeyguardDisabled setKeyguardDisabled()} 333</li> 334 335<li> 336Disable the status bar using 337{@link android.app.admin.DevicePolicyManager#setStatusBarDisabled setStatusBarDisabled()} 338</li> 339 340<li> 341Keep a device’s screen on while plugged in via 342{@link android.provider.Settings.Global#STAY_ON_WHILE_PLUGGED_IN} 343</li> 344 345<li> 346Set default user restriction for managed configurations via 347{@link android.app.admin.DevicePolicyManager#addUserRestriction addUserRestriction()} 348</li> 349 350<li> 351Set system update policies using 352{@link android.app.admin.DevicePolicyManager#setSystemUpdatePolicy setSystemUpdatePolicy()} 353</li> 354 355<li> 356Ensure your app is launched on reboot by setting it as the default launcher 357</li> 358</ul> 359</li> 360</ol> 361 362<p> 363Here’s an example of how to implement an activity that starts lock task mode 364and implements the relevant COSU device management APIs: 365</p> 366 367<pre> 368public class CosuActivity extends Activity { 369 370 private ComponentName mAdminComponentName; 371 private DevicePolicyManager mDevicePolicyManager; 372 private PackageManager mPackageManager; 373 private static final String Battery_PLUGGED_ANY = Integer.toString( 374 BatteryManager.BATTERY_PLUGGED_AC | 375 BatteryManager.BATTERY_PLUGGED_USB | 376 BatteryManager.BATTERY_PLUGGED_WIRELESS); 377 378 private static final String DONT_STAY_ON = "0"; 379 380 @Override 381 protected void onCreate(Bundle savedInstanceState) { 382 super.onCreate(savedInstanceState); 383 384 mAdminComponentName = DeviceAdminReceiver.getComponentName(this); 385 mDevicePolicyManager = (DevicePolicyManager) getSystemService( 386 Context.DEVICE_POLICY_SERVICE); 387 mPackageManager = getPackageManager(); 388 setDefaultCosuPolicies(true); 389 } 390 391 @Override 392 protected void onStart() { 393 super.onStart(); 394 395 // start lock task mode if it's not already active 396 ActivityManager am = (ActivityManager) getSystemService( 397 Context.ACTIVITY_SERVICE); 398 // ActivityManager.getLockTaskModeState api is not available in pre-M. 399 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 400 if (!am.isInLockTaskMode()) { 401 startLockTask(); 402 } 403 } else { 404 if (am.getLockTaskModeState() == 405 ActivityManager.LOCK_TASK_MODE_NONE) { 406 startLockTask(); 407 } 408 } 409 } 410 411 private void setDefaultCosuPolicies(boolean active) { 412 // set user restrictions 413 setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, active); 414 setUserRestriction(UserManager.DISALLOW_FACTORY_RESET, active); 415 setUserRestriction(UserManager.DISALLOW_ADD_USER, active); 416 setUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, active); 417 setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, active); 418 419 // disable keyguard and status bar 420 mDevicePolicyManager.setKeyguardDisabled(mAdminComponentName, active); 421 mDevicePolicyManager.setStatusBarDisabled(mAdminComponentName, active); 422 423 // enable STAY_ON_WHILE_PLUGGED_IN 424 enableStayOnWhilePluggedIn(active); 425 426 // set System Update policy 427 428 if (active){ 429 mDevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName, 430 SystemUpdatePolicy.createWindowedInstallPolicy(60,120)); 431 } else { 432 DevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName, null); 433 } 434 435 // set this Activity as a lock task package 436 437 mDevicePolicyManager.setLockTaskPackages(mAdminComponentName, 438 active ? new String[]{getPackageName()} : new String[]{}); 439 440 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN); 441 intentFilter.addCategory(Intent.CATEGORY_HOME); 442 intentFilter.addCategory(Intent.CATEGORY_DEFAULT); 443 444 if (active) { 445 // set Cosu activity as home intent receiver so that it is started 446 // on reboot 447 mDevicePolicyManager.addPersistentPreferredActivity( 448 mAdminComponentName, intentFilter, new ComponentName( 449 getPackageName(), CosuActivity.class.getName())); 450 } else { 451 mDevicePolicyManager.clearPackagePersistentPreferredActivities( 452 mAdminComponentName, getPackageName()); 453 } 454 } 455 456 private void setUserRestriction(String restriction, boolean disallow) { 457 if (disallow) { 458 mDevicePolicyManager.addUserRestriction(mAdminComponentName, 459 restriction); 460 } else { 461 mDevicePolicyManager.clearUserRestriction(mAdminComponentName, 462 restriction); 463 } 464 } 465 466 private void enableStayOnWhilePluggedIn(boolean enabled) { 467 if (enabled) { 468 mDevicePolicyManager.setGlobalSetting( 469 mAdminComponentName, 470 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 471 Battery_PLUGGED_ANY); 472 } else { 473 mDevicePolicyManager.setGlobalSetting( 474 mAdminComponentName, 475 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, DONT_STAY_ON); 476 } 477 } 478 479 // TODO: Implement the rest of the Activity 480} 481</pre> 482 483 484<h2 id="testing-plan"> 485 Develop a test plan for COSU 486</h2> 487 488<p> 489 If you’re planning to support a third-party EMM, develop an end-to-end 490 testing plan utilizing the EMM’s app. We also provide testing resources, 491 which you can use to create your own Test Device Policy Client (Test DPC): 492</p> 493 494<ul> 495<li> 496<a class="external-link" href="https://play.google.com/store/search?q=testdpc">TestDPC on Google Play</a> 497</li> 498<li> 499<a class="external-link" href="https://github.com/googlesamples/android-testdpc/tree/master/app/src/main/java/com/afwsamples/testdpc/cosu">TestDPC for COSU source code on GitHub</a> 500</li> 501<li> 502<a class="external-link" href="https://github.com/googlesamples/android-testdpc">Test Device Policy Control app source code on GitHub</a> 503</li> 504</ul> 505