aboutsummaryrefslogtreecommitdiff
path: root/en/devices/tech/display/retail-mode.html
blob: 5e1247352488916cdbdd0032f2f7b571df54adaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
<html devsite>
  <head>
    <title>Retail Demo Mode</title>
    <meta name="project_path" value="/_project.yaml" />
    <meta name="book_path" value="/_book.yaml" />
  </head>
  <body>
  <!--
      Copyright 2017 The Android Open Source Project

      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
  -->

<p>
Android 7.1.1 and later offer system-level support for retail mode so
users may readily examine the devices in action. Android 8.1 revises
this support to create demo users via Device Policy Manager. This
allows much greater OEM customization to the standard retail mode.
</p>

<h2 id=android-8-1-and-later>Android 8.1 and later</h2>

<p>
Through Device Policy Manager, Android 8.1 supports demonstrating
device functionality to users in retail stores. While Device Policy Manager's
APIs can be used on versions prior to 8.1, demo-type users cannot be created
with <a href="https://developer.android.com/reference/android/app/admin/DevicePolicyManager.html#createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int)">
createAndManageUser</a> prior to 8.1.
</p>

<h3 id="implementation">Implementation</h3>

<h4 id="provisioning">Provisioning</h4>
<p>
Set <code>Settings.Global.DEVICE_DEMO_MODE</code> to 1 prior to
provisioning to indicate that the device should enter retail mode. System
Server will use this flag to manage aspects of retail mode, such as power
profile. In addition, retail employees must grant device ownership to the
demo application. Once a consumer setup is complete, device owners cannot
be set.
</p>

<h4 id="create-demo-app">Creating the demo application</h4>
<p>
Device owner apps do not need elevated privileges or pre-installation on the
system image. They are mostly implemented like traditional apps, with the
following differences:
</p>
<ul>
  <li>All device owner apps must extend the <code>DeviceAdminReceiver</code>
component, which serves as the authorization token for all Device Policy
Manager APIs. The component must hold the <code>android.permission.BIND_DEVICE_ADMIN</code>
permission, include the requested special policies as metadata, and filter the
<code>android.app.action.PROFILE_PROVISIONING_COMPLETE</code> and
 <code>android.app.action.DEVICE_ADMIN_ENABLED</code> intents.</li>
  <li>The <code>DevicePolicyManager#MAKE_USER_DEMO</code> flag, which is set
to create special demo-type users, is a hidden API. This flag is a constant 0x4.</li>
  <li>Device ownership can be assigned only via Managed Provisioning.</li>
</ul>

<h4 id="device-policy-manager">Device Policy Manager</h4>
<p>
Device Policy Manager APIs grant all Device Owner (DO) and Profile Owner (PO)
rights, except for installing packages, which is automatically allowed. A PO
affiliated with a DO can use an AIDL interface to access rights that are only
granted to the DO. Functionality available includes:
</p>
<ul>
 <li>Create users. Users created through the DevicePolicyManager are
automatically set as PO.</li>
 <li>Switch users.</li>
 <li>Set the permission policy to <code>PERMISSION_POLICY_AUTO_GRANT</code>
which will automatically grant all runtime permissions. Permissions can also be
granted more narrowly: a single permission to a single app. This does not
apply to Appops permissions, which users must still grant on a per-user,
per-app basis.</li>
 <li>Add user restrictions. Restrictions relevant to retail mode may include,
but are not limited to:
   <ul>
     <li><code>DISALLOW_MODIFY_ACCOUNTS</code></li>
     <li><code>DISALLOW_USB_FILE_TRANSFER</code></li>
     <li><code>DISALLOW_DEBUGGING_FEATURES</code></li>
     <li><code>DISALLOW_CONFIG_WIFI</code></li>
     <li><code>DISALLOW_CONFIG_BLUETOOTH</code></li>
     <li><code>DISALLOW_INSTALL_UNKNOWN_SOURCES</code></li>
     <li><code>DISALLOW_CONFIG_MOBILE_NETWORKS</code></li>
   </ul>
 </li>
 <li>Enable automatic system updates. Devices will automatically download and apply
OTA updates.</li>
 <li>Set LockTask allowed packages.</li>
 <li>Factory reset the device.</li>
 <li>Disable the keyguard.</li>
 <li>Prevent setting passwords / fingerprints.</li>
 <li>Control Wi-fi network changes. When used with the <code>DISALLOW_CONFIG_WIFI</code>
user restriction, device owner apps can control access to the wifi network selection
setting.</li>
 <li>Reboot the device.</li>
 <li>Install packages through <a href="https://developer.android.com/reference/android/content/pm/PackageInstaller.html">
PackageInstaller</a>.</li>
 <li>Set a whitelisted set of <a href="https://developer.android.com/reference/android/provider/Settings.Global.html">
Settings.Global</a>, <a href="https://developer.android.com/reference/android/provider/Settings.Secure.html">
Settings.Secure</a>, and <a href="https://developer.android.com/reference/android/provider/Settings.System.html">
Settings.System</a> settings.</li>
 <li>Block packages from being uninstalled.</li>
</ul>

<h3 id="examples-additional-resources">Examples and additional resources</h3>
<ul>
 <li><a href="/devices/tech/admin/multi-user">
Android Developer definitions</a> of users, profiles, and accounts</li>
 <li><a href="https://developer.android.com/reference/android/app/admin/DevicePolicyManager.html">
Device Policy Manager API documentation</a></li>
 <li><a href="https://developer.android.com/samples/DeviceOwner/index.html">
Sample Device Owner app</a></li>
</ul>

<h3 id="validation">Validation</h3>
<p>
CTS does not cover Retail Demo Mode because it is an optional feature. Testing
should be conducted manually or with unit tests for the demo application.
</p>

<h2 id="retail-demo-mode-8-and-earlier">Android 8.0 and earlier</h2>

<p>
Android 7.1.1 introduced retail demo mode and provided a simple API to play a
demonstration video. This implementation was removed in Android 8.1.
</p>

<h3 id="lifecycle">Lifecycle</h3>

<img src="/devices/tech/display/images/retail-demo-flow.png" alt="retail demo mode flow" width="XXX" id="retail-demo-flow" />
<p class="img-caption">
  <strong>Figure 1.</strong> Retail demonstration mode option in Language selection
</p>

<h4 id="setup-wizard-suw">Setup Wizard (SUW)</h4>

<p>
Retail employees can enable retail mode directly from the first screen of any setup
wizard by selecting the language <strong>Retail demo</strong> at the bottom of
the list. This option is available for new devices shipped fresh from the
factory. Once a consumer setup has completed, retail mode may no longer be
available.  Once selected, the device finishes SUW with an abbreviated flow.
</p>

<img src="/devices/tech/display/images/retail-demo-wizard.png" alt="retail demo wizard use" width="XXX" id="retail-demo-wizard" />
<p class="img-caption">
  <strong>Figure 2.</strong> Retail demonstration mode option in Language
selection
</p>

<h4 id="guest-session">Guest session</h4>

<p>
When the device enters retail mode, it switches to a new demo user and
automatically starts the custom launcher specified in the overlay resource
(described under Implementation).  By default, this custom launcher plays the
demo video on repeat until the user touches the screen to begin a guest session.
At that time, the custom launcher starts the system launcher and then exits.
OEMs can alter the custom launcher to additionally launch another service or
activity on exit. See the <em>Implementation</em> section for details.
</p>

<p>
In order to maintain the integrity of retail mode, keyguard is disabled and
certain actions from Quick Settings that could adversely affect retail mode are
also disallowed, including:
</p>

<ul>
  <li>Airplane mode toggle
  <li>Removing or modifying Wi-Fi access points (Settings)
  <li>Changing carrier (Settings)
  <li>Configuring hotspot (Settings)
  <li>User switching
</ul>

<p>
Additionally, access is also blocked to some global settings that can affect
retail mode by disabling:
</p>

<ul>
  <li>Wi-Fi settings
  <li>Cellular network configuration options, particularly hotspots
  <li>Bluetooth configuration
  <li>Backup & Reset, Date & Time, and Mobile Networks (they do not show up at
all)
</ul>

<p>
If the user is idle for some period of time (90 seconds by default), retail mode
will show a system dialog to prompt the user to either exit the session or
continue. If the user chooses to exit or if there's no response for five
seconds, retail mode kills/wipes the current demo user, switches to a new demo
user, and loops through the original video again. If someone turns off the
screen using the power button, it comes back on automatically after a few
seconds.
</p>

<p>
After exiting a demo session, devices mute themselves and reset some global
settings, including:
</p>

<ul>
  <li>Brightness
  <li>Auto-rotation
  <li>Flashlight
  <li>Language
  <li>Accessibility</li></ul>

<h4 id="exiting-retail-mode">Exiting retail mode</h4>

<p>
In order to exit retail mode, retail employees must factory reset the device
from the boot loader.
</p>

<h3 id="examples-and-source">Examples and source</h3>

<p>
Find the custom launcher that plays a video in a loop within:</p>
<pre class="devsite-click-to-copy">
/packages/apps/RetailDemo
</pre>

<h3 id="implementation">Implementation</h3>

<h4 id="enabling-retaildemomodeservice">Enabling RetailDemoModeService</h4>

<p>
Setup wizard sets a Global setting <code>Global.DEVICE_DEMO_MODE=true</code> to
indicate that the device has entered retail mode. Upon seeing this setting,
<code>RetailDemoModeService</code> creates and switches to demo user when user 0
is started, enables the custom launcher specified in an overlay resource, and
disables SUW.  System Server and SystemUI also use this flag to manage aspects
of retail mode.
</p>

<h4 id="setting-custom-launcher-or-video-player">Setting custom launcher or
video player</h4>

<p>
An OEM specifies a custom launcher by overriding the framework resource
<code>config_demoModeLauncherComponent</code> specified in:
<code>/frameworks/base/core/res/res/config.xml</code>
</p>

<p>
For example, with:
</p>

<pre class="devsite-click-to-copy">
&lt;!-- Component that is the default launcher when Retail Mode is enabled. --&gt;
&lt;string name="config_demoModeLauncherComponent"&gt;com.android.retaildemo/.DemoPlayer&lt;/string&gt;
</pre>
<p>
The retail demo DemoPlayer app located at
<code>/packages/apps/RetailDemo</code> is the default custom launcher in the
Android Open Source Project (AOSP).  The app looks for a video in
<code>/data/preloads/demo/retail_demo.mp4</code> and plays it in a loop. When
the user touches the screen, the custom launcher disables its activity
component, which results in the default system launcher starting up.
</p>

<p>The custom launcher must have its custom component marked as disabled by default so that it
doesn't show up in non-demo scenarios. In the demo scenario, System Server
enables the specified <code>config_demoModeLauncherComponent</code> when
starting a new demo session.
</p>

<p>
Setup wizard also looks for the above video to provide an affordance to enter
retail mode. SUW can be modified to look for some other OEM-specific sign that
retail mode is supported if the video is not a part of the demo.
</p>

<p>
If there are system A/B partitions, the system B partition must contain the demo
video at <code>/preloads/demo</code>. This gets copied to
<code>/data/preloads/demo</code> on first boot.
</p>

<p>
To set retail mode-specific settings, use:
<code>Settings.Global.retail_demo_mode_constants</code>. E.g.:
<code>user_inactivity_timeout_ms=90000,warning_dialog_timeout_ms=10000</code>
</p>

<p class="note"><strong>Note:</strong> 90000 milliseconds is the current
timeout default but is configurable.
</p>

<h4 id="finding-sample-images">Finding sample images</h4>

<p>
This feature places sample photos in a special folder that is visible to any
gallery app. The photos are available only in demo mode and cannot be modified
by the demo user as they are in a protected directory.
</p>

<h4 id="preventing-google-accounts">Preventing Google accounts</h4>

<p>
Certain restrictions are set in the guest user, similar to managed
device/profile policies that prevent apps and users from performing certain
operations. One of these restrictions is <code>DISALLOW_MODIFY_ACCOUNTS</code>.
With this restriction, AccountManager and Settings do not allow the addition of
accounts. Some Google apps react to this restriction and show an error message,
and others will not prompt for an account (such as YouTube and Photos).
</p>

<p>
OEM apps should also check if <code>DISALLOW_MODIFY_ACCOUNTS</code> is set. But this is a
general problem not unique to retail mode. It is likely already solved for
enterprise use cases.
</p>

<h4 id="customizing-the-system-launcher">Customizing the system launcher</h4>

<p>
OEMs are free to choose their layout but should include apps that function well
on the home screen and hotseat.
</p>

<h4 id="Customizing-built-in-apps">Customizing built-in apps for retail demo mode</h4>

<p>
Built-in apps may have their experience for retail demo mode customized by
calling the API <code>UserManager.isDemoUser()</code> to see if the app is
launched in a demo environment.
</p>

<h4 id="following-demo-video-guidelines">Following demo video guidelines</h4>

<p>
Demonstration videos should be in portrait layout (or natural orientation of the
device, if tablet) and can be any length greater than five seconds. Content
should not result in burn-in, since it will be played 24/7 when on display.
</p>

<h3 id="maintenance">Maintenance</h3>

<h4 id="bringing-the-device-out-of-retail-mode">Bringing the device out of
retail mode</h4>

<p>
This can be done only by factory resetting from the boot loader.
</p>

<h4 id="auto-ota-of-system-software">Auto-OTA of system software</h4>

<p>
By default, when retail mode is enabled, device policy is set to over-the-air
(OTA) update automatically. Retail devices will download, reboot, and install
the update (respecting battery thresholds) without confirmation even if it is
marked as optional.
</p>

<p class="caution"><strong>Caution:</strong>
If using System A/B partitions for OTA, once an OTA is received, the device
cannot find original retail mode resources in the System B partition. So any
subsequent factory reset will result in an inability to go back into retail
mode.
</p>

<h4 id="updating-demo-video-via-the-web">Updating demo video via the web</h4>

<p>
The RetailDemo app in <code>/packages/apps/RetailDemo</code> has the ability to
update the demo video if there is network connectivity. The URL to download the
video from can be configured by overriding the following string value in the
RetailDemo app:
</p>

<pre class="devsite-click-to-copy">
&lt;!-- URL where the retail demo video can be downloaded from. --&gt;
&lt;string name="retail_demo_video_download_url"&gt;&lt;/string&gt;
</pre>

<p>
If different videos need to be used in different regions, then different
download URLs can be configured by using locale-specific string resources
<code>res/values-*/strings.xml. </code>For example, if different videos need to
be used in the U.S. and the U.K., then corresponding download URLs can be placed
in <code>res/values-en-rUS/strings.xml</code> and
<code>res/values-en-rGB/strings.xml</code>, respectively.
</p>

<p>
In <code>res/values-en-rUS/strings.xml</code>:
</p>

<pre class="devsite-click-to-copy">
&lt;string name="retail_demo_video_download_url"&gt;download URL for US video goes here&lt;/string&gt;
</pre>

<p>
And similarly in <code>res/values-en-rGB/strings.xml</code>:
</p>

<pre class="devsite-click-to-copy">
&lt;string name="retail_demo_video_download_url"&gt;download URL for UK video goes here&lt;/string&gt;
</pre>

<p>
This video will be downloaded at most once per every device reboot. When the
video on the device is being played, RetailDemo app will check in the background
if the download URL is provided and the video at the URL is newer than the one
being played.

<p>
If so, RetailDemo app will download this video and start playing
it. Once this video is downloaded, the downloaded video will be used for playing
in the demo sessions going forward. None of the checks happen again until after
next reboot.
</p>

  </body>
</html>