• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>&lt;activity android:name=".MainActivity" android:lockTaskMode="if_whitelisted"&gt;</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    &#64;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    &#64;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