RetailDemoModeService.java revision b632c5546968bc20e60e5b86ded4c41612a47c52
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.retaildemo;
18
19import android.Manifest;
20import android.app.ActivityManagerInternal;
21import android.app.ActivityManagerNative;
22import android.app.AppGlobals;
23import android.app.Notification;
24import android.app.NotificationManager;
25import android.app.PendingIntent;
26import android.app.RetailDemoModeServiceInternal;
27import android.content.BroadcastReceiver;
28import android.content.ComponentName;
29import android.content.ContentResolver;
30import android.content.Context;
31import android.content.DialogInterface;
32import android.content.Intent;
33import android.content.IntentFilter;
34import android.content.pm.IPackageManager;
35import android.content.pm.PackageManager;
36import android.content.pm.ResolveInfo;
37import android.content.pm.UserInfo;
38import android.content.res.Configuration;
39import android.database.ContentObserver;
40import android.hardware.camera2.CameraAccessException;
41import android.hardware.camera2.CameraCharacteristics;
42import android.hardware.camera2.CameraManager;
43import android.media.AudioManager;
44import android.media.AudioSystem;
45import android.net.Uri;
46import android.net.wifi.WifiManager;
47import android.os.Environment;
48import android.os.FileUtils;
49import android.os.Handler;
50import android.os.Looper;
51import android.os.Message;
52import android.os.PowerManager;
53import android.os.RemoteException;
54import android.os.SystemClock;
55import android.os.SystemProperties;
56import android.os.UserHandle;
57import android.os.UserManager;
58import android.provider.CallLog;
59import android.provider.MediaStore;
60import android.provider.Settings;
61import android.text.TextUtils;
62import android.util.KeyValueListParser;
63import android.util.Slog;
64import com.android.internal.os.BackgroundThread;
65import com.android.internal.R;
66import com.android.internal.annotations.GuardedBy;
67import com.android.internal.logging.MetricsLogger;
68import com.android.internal.widget.LockPatternUtils;
69import com.android.server.LocalServices;
70import com.android.server.ServiceThread;
71import com.android.server.SystemService;
72import com.android.server.am.ActivityManagerService;
73import com.android.server.retaildemo.UserInactivityCountdownDialog.OnCountDownExpiredListener;
74
75import java.io.File;
76import java.util.ArrayList;
77
78public class RetailDemoModeService extends SystemService {
79    private static final boolean DEBUG = false;
80
81    private static final String TAG = RetailDemoModeService.class.getSimpleName();
82    private static final String DEMO_USER_NAME = "Demo";
83    private static final String ACTION_RESET_DEMO =
84            "com.android.server.retaildemo.ACTION_RESET_DEMO";
85    private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
86
87    private static final int MSG_TURN_SCREEN_ON = 0;
88    private static final int MSG_INACTIVITY_TIME_OUT = 1;
89    private static final int MSG_START_NEW_SESSION = 2;
90
91    private static final long SCREEN_WAKEUP_DELAY = 2500;
92    private static final long USER_INACTIVITY_TIMEOUT_MIN = 10000;
93    private static final long USER_INACTIVITY_TIMEOUT_DEFAULT = 90000;
94    private static final long WARNING_DIALOG_TIMEOUT_DEFAULT = 0;
95    private static final long MILLIS_PER_SECOND = 1000;
96
97    private static final int[] VOLUME_STREAMS_TO_MUTE = {
98            AudioSystem.STREAM_RING,
99            AudioSystem.STREAM_MUSIC
100    };
101
102    // Tron Vars
103    private static final String DEMO_SESSION_COUNT = "retail_demo_session_count";
104    private static final String DEMO_SESSION_DURATION = "retail_demo_session_duration";
105
106    boolean mDeviceInDemoMode;
107    boolean mIsCarrierDemoMode;
108    int mCurrentUserId = UserHandle.USER_SYSTEM;
109    long mUserInactivityTimeout;
110    long mWarningDialogTimeout;
111    private ActivityManagerService mAms;
112    private ActivityManagerInternal mAmi;
113    private AudioManager mAudioManager;
114    private NotificationManager mNm;
115    private UserManager mUm;
116    private PowerManager mPm;
117    private PowerManager.WakeLock mWakeLock;
118    Handler mHandler;
119    private ServiceThread mHandlerThread;
120    private PendingIntent mResetDemoPendingIntent;
121    private CameraManager mCameraManager;
122    private WifiManager mWifiManager;
123    private String[] mCameraIdsWithFlash;
124    private Configuration mSystemUserConfiguration;
125    private PreloadAppsInstaller mPreloadAppsInstaller;
126
127    final Object mActivityLock = new Object();
128    // Whether the newly created demo user has interacted with the screen yet
129    @GuardedBy("mActivityLock")
130    boolean mUserUntouched;
131    @GuardedBy("mActivityLock")
132    long mFirstUserActivityTime;
133    @GuardedBy("mActivityLock")
134    long mLastUserActivityTime;
135
136    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
137        @Override
138        public void onReceive(Context context, Intent intent) {
139            if (!mDeviceInDemoMode) {
140                return;
141            }
142            final String action = intent.getAction();
143            switch (action) {
144                case Intent.ACTION_SCREEN_OFF:
145                    mHandler.removeMessages(MSG_TURN_SCREEN_ON);
146                    mHandler.sendEmptyMessageDelayed(MSG_TURN_SCREEN_ON, SCREEN_WAKEUP_DELAY);
147                    break;
148                case ACTION_RESET_DEMO:
149                    mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
150                    break;
151            }
152        }
153    };
154
155    final class MainHandler extends Handler {
156
157        MainHandler(Looper looper) {
158            super(looper, null, true);
159        }
160
161        @Override
162        public void handleMessage(Message msg) {
163            switch (msg.what) {
164                case MSG_TURN_SCREEN_ON:
165                    if (mWakeLock.isHeld()) {
166                        mWakeLock.release();
167                    }
168                    mWakeLock.acquire();
169                    break;
170                case MSG_INACTIVITY_TIME_OUT:
171                    if (!mIsCarrierDemoMode && isDemoLauncherDisabled()) {
172                        Slog.i(TAG, "User inactivity timeout reached");
173                        showInactivityCountdownDialog();
174                    }
175                    break;
176                case MSG_START_NEW_SESSION:
177                    if (DEBUG) {
178                        Slog.d(TAG, "Switching to a new demo user");
179                    }
180                    removeMessages(MSG_START_NEW_SESSION);
181                    removeMessages(MSG_INACTIVITY_TIME_OUT);
182                    if (!mIsCarrierDemoMode && mCurrentUserId != UserHandle.USER_SYSTEM) {
183                        logSessionDuration();
184                    }
185
186                    UserInfo demoUser = null;
187                    if (mIsCarrierDemoMode) {
188                        // Re-use the existing demo user in carrier demo mode.
189                        for (UserInfo user : getUserManager().getUsers()) {
190                            if (user.isDemo()) {
191                                demoUser = user;
192                                break;
193                            }
194                        }
195                    }
196
197                    if (demoUser == null) {
198                        // User in carrier demo mode should survive reboots.
199                        final int flags = UserInfo.FLAG_DEMO
200                                | (mIsCarrierDemoMode ? 0 : UserInfo.FLAG_EPHEMERAL);
201                        demoUser = getUserManager().createUser(DEMO_USER_NAME, flags);
202                    }
203
204                    if (demoUser != null && mCurrentUserId != demoUser.id) {
205                        setupDemoUser(demoUser);
206                        getActivityManager().switchUser(demoUser.id);
207                    }
208                    break;
209            }
210        }
211    }
212
213    private class SettingsObserver extends ContentObserver {
214
215        private final static String KEY_USER_INACTIVITY_TIMEOUT = "user_inactivity_timeout_ms";
216        private final static String KEY_WARNING_DIALOG_TIMEOUT = "warning_dialog_timeout_ms";
217
218        private final Uri mDeviceProvisionedUri = Settings.Global
219                .getUriFor(Settings.Global.DEVICE_PROVISIONED);
220        private final Uri mRetailDemoConstantsUri = Settings.Global
221                .getUriFor(Settings.Global.RETAIL_DEMO_MODE_CONSTANTS);
222
223        private final KeyValueListParser mParser = new KeyValueListParser(',');
224
225        public SettingsObserver(Handler handler) {
226            super(handler);
227        }
228
229        public void register() {
230            ContentResolver cr = getContext().getContentResolver();
231            cr.registerContentObserver(mDeviceProvisionedUri, false, this, UserHandle.USER_SYSTEM);
232            cr.registerContentObserver(mRetailDemoConstantsUri, false, this,
233                    UserHandle.USER_SYSTEM);
234        }
235
236        @Override
237        public void onChange(boolean selfChange, Uri uri) {
238            if (mRetailDemoConstantsUri.equals(uri)) {
239                refreshTimeoutConstants();
240                return;
241            }
242            // If device is provisioned and left demo mode - run the cleanup in demo folder
243            if (isDeviceProvisioned()) {
244                if (UserManager.isDeviceInDemoMode(getContext())) {
245                    putDeviceInDemoMode();
246                } else {
247                    SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0");
248
249                    // Run on the bg thread to not block the fg thread
250                    BackgroundThread.getHandler().post(new Runnable() {
251                        @Override
252                        public void run() {
253                            if (!deletePreloadsFolderContents()) {
254                                Slog.w(TAG, "Failed to delete preloads folder contents");
255                            }
256                        }
257                    });
258
259                    if (mWakeLock.isHeld()) {
260                        mWakeLock.release();
261                    }
262                }
263            }
264        }
265
266        private void refreshTimeoutConstants() {
267            try {
268                mParser.setString(Settings.Global.getString(getContext().getContentResolver(),
269                    Settings.Global.RETAIL_DEMO_MODE_CONSTANTS));
270            } catch (IllegalArgumentException exc) {
271                Slog.e(TAG, "Invalid string passed to KeyValueListParser");
272                // Consuming the exception to fall back to default values.
273            }
274            mWarningDialogTimeout = mParser.getLong(KEY_WARNING_DIALOG_TIMEOUT,
275                    WARNING_DIALOG_TIMEOUT_DEFAULT);
276            mUserInactivityTimeout = mParser.getLong(KEY_USER_INACTIVITY_TIMEOUT,
277                    USER_INACTIVITY_TIMEOUT_DEFAULT);
278            mUserInactivityTimeout = Math.max(mUserInactivityTimeout, USER_INACTIVITY_TIMEOUT_MIN);
279        }
280    }
281
282    private void showInactivityCountdownDialog() {
283        UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
284                mWarningDialogTimeout, MILLIS_PER_SECOND);
285        dialog.setNegativeButtonClickListener(null);
286        dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() {
287            @Override
288            public void onClick(DialogInterface dialog, int which) {
289                mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
290            }
291        });
292        dialog.setOnCountDownExpiredListener(new OnCountDownExpiredListener() {
293            @Override
294            public void onCountDownExpired() {
295                mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
296            }
297        });
298        dialog.show();
299    }
300
301    public RetailDemoModeService(Context context) {
302        super(context);
303        synchronized (mActivityLock) {
304            mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis();
305        }
306    }
307
308    private Notification createResetNotification() {
309        return new Notification.Builder(getContext())
310                .setContentTitle(getContext().getString(R.string.reset_retail_demo_mode_title))
311                .setContentText(getContext().getString(R.string.reset_retail_demo_mode_text))
312                .setOngoing(true)
313                .setSmallIcon(R.drawable.platlogo)
314                .setShowWhen(false)
315                .setVisibility(Notification.VISIBILITY_PUBLIC)
316                .setContentIntent(getResetDemoPendingIntent())
317                .setColor(getContext().getColor(R.color.system_notification_accent_color))
318                .build();
319    }
320
321    private PendingIntent getResetDemoPendingIntent() {
322        if (mResetDemoPendingIntent == null) {
323            Intent intent = new Intent(ACTION_RESET_DEMO);
324            mResetDemoPendingIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
325        }
326        return mResetDemoPendingIntent;
327    }
328
329    boolean isDemoLauncherDisabled() {
330        int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
331        try {
332            final IPackageManager iPm = AppGlobals.getPackageManager();
333            final String demoLauncherComponent =
334                    getContext().getString(R.string.config_demoModeLauncherComponent);
335            enabledState = iPm.getComponentEnabledSetting(
336                    ComponentName.unflattenFromString(demoLauncherComponent), mCurrentUserId);
337        } catch (RemoteException re) {
338            Slog.e(TAG, "Error retrieving demo launcher enabled setting", re);
339        }
340        return enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
341    }
342
343    private void setupDemoUser(UserInfo userInfo) {
344        final UserManager um = getUserManager();
345        final UserHandle user = UserHandle.of(userInfo.id);
346        um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
347        um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
348        um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
349        um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
350        um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
351        um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
352        // Set this to false because the default is true on user creation
353        um.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
354        // Disallow rebooting in safe mode - controlled by user 0
355        um.setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
356
357        Settings.Secure.putIntForUser(getContext().getContentResolver(),
358                Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
359        Settings.Global.putInt(getContext().getContentResolver(),
360                Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
361
362        grantRuntimePermissionToCamera(user);
363        clearPrimaryCallLog();
364
365        if (!mIsCarrierDemoMode) {
366            // Enable demo launcher.
367            final String demoLauncher = getContext().getString(
368                    R.string.config_demoModeLauncherComponent);
369            if (!TextUtils.isEmpty(demoLauncher)) {
370                final ComponentName componentToEnable =
371                        ComponentName.unflattenFromString(demoLauncher);
372                final String packageName = componentToEnable.getPackageName();
373                try {
374                    final IPackageManager iPm = AppGlobals.getPackageManager();
375                    iPm.setComponentEnabledSetting(componentToEnable,
376                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id);
377                    iPm.setApplicationEnabledSetting(packageName,
378                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
379                } catch (RemoteException re) {
380                    // Internal, shouldn't happen
381                }
382            }
383        } else {
384            // Set the carrier demo mode setting for the demo user.
385            final String carrierDemoModeSetting = getContext().getString(
386                    R.string.config_carrierDemoModeSetting);
387            Settings.Secure.putIntForUser(getContext().getContentResolver(),
388                    carrierDemoModeSetting, 1, userInfo.id);
389
390            // Enable packages for carrier demo mode.
391            final String packageList = getContext().getString(
392                    R.string.config_carrierDemoModePackages);
393            final String[] packageNames = packageList == null ? new String[0]
394                    : TextUtils.split(packageList, ",");
395            final IPackageManager iPm = AppGlobals.getPackageManager();
396            for (String packageName : packageNames) {
397                try {
398                    iPm.setApplicationEnabledSetting(packageName,
399                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
400                } catch (RemoteException re) {
401                    Slog.e(TAG, "Error enabling application: " + packageName, re);
402                }
403            }
404        }
405    }
406
407    private void grantRuntimePermissionToCamera(UserHandle user) {
408        final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
409        final PackageManager pm = getContext().getPackageManager();
410        final ResolveInfo handler = pm.resolveActivityAsUser(cameraIntent,
411                PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
412                user.getIdentifier());
413        if (handler == null || handler.activityInfo == null) {
414            return;
415        }
416        try {
417            pm.grantRuntimePermission(handler.activityInfo.packageName,
418                    Manifest.permission.ACCESS_FINE_LOCATION, user);
419        } catch (Exception e) {
420            // Ignore
421        }
422    }
423
424    private void clearPrimaryCallLog() {
425        final ContentResolver resolver = getContext().getContentResolver();
426
427        // Deleting primary user call log so that it doesn't get copied to the new demo user
428        final Uri uri = CallLog.Calls.CONTENT_URI;
429        try {
430            resolver.delete(uri, null, null);
431        } catch (Exception e) {
432            Slog.w(TAG, "Deleting call log failed: " + e);
433        }
434    }
435
436    void logSessionDuration() {
437        final int sessionDuration;
438        synchronized (mActivityLock) {
439            sessionDuration = (int) ((mLastUserActivityTime - mFirstUserActivityTime) / 1000);
440        }
441        MetricsLogger.histogram(getContext(), DEMO_SESSION_DURATION, sessionDuration);
442    }
443
444    private ActivityManagerService getActivityManager() {
445        if (mAms == null) {
446            mAms = (ActivityManagerService) ActivityManagerNative.getDefault();
447        }
448        return mAms;
449    }
450
451    private UserManager getUserManager() {
452        if (mUm == null) {
453            mUm = getContext().getSystemService(UserManager.class);
454        }
455        return mUm;
456    }
457
458    private AudioManager getAudioManager() {
459        if (mAudioManager == null) {
460            mAudioManager = getContext().getSystemService(AudioManager.class);
461        }
462        return mAudioManager;
463    }
464
465    private boolean isDeviceProvisioned() {
466        return Settings.Global.getInt(
467                getContext().getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
468    }
469
470    private boolean deletePreloadsFolderContents() {
471        final File dir = Environment.getDataPreloadsDirectory();
472        Slog.i(TAG, "Deleting contents of " + dir);
473        return FileUtils.deleteContents(dir);
474    }
475
476    private void registerBroadcastReceiver() {
477        final IntentFilter filter = new IntentFilter();
478        if (!mIsCarrierDemoMode) {
479            filter.addAction(Intent.ACTION_SCREEN_OFF);
480        }
481        filter.addAction(ACTION_RESET_DEMO);
482        getContext().registerReceiver(mBroadcastReceiver, filter);
483    }
484
485    private String[] getCameraIdsWithFlash() {
486        ArrayList<String> cameraIdsList = new ArrayList<String>();
487        try {
488            for (String cameraId : mCameraManager.getCameraIdList()) {
489                CameraCharacteristics c = mCameraManager.getCameraCharacteristics(cameraId);
490                if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) {
491                    cameraIdsList.add(cameraId);
492                }
493            }
494        } catch (CameraAccessException e) {
495            Slog.e(TAG, "Unable to access camera while getting camera id list", e);
496        }
497        return cameraIdsList.toArray(new String[cameraIdsList.size()]);
498    }
499
500    private void turnOffAllFlashLights() {
501        for (String cameraId : mCameraIdsWithFlash) {
502            try {
503                mCameraManager.setTorchMode(cameraId, false);
504            } catch (CameraAccessException e) {
505                Slog.e(TAG, "Unable to access camera " + cameraId + " while turning off flash", e);
506            }
507        }
508    }
509
510    private void muteVolumeStreams() {
511        for (int stream : VOLUME_STREAMS_TO_MUTE) {
512            getAudioManager().setStreamVolume(stream, getAudioManager().getStreamMinVolume(stream),
513                    0);
514        }
515    }
516
517    private Configuration getSystemUsersConfiguration() {
518        if (mSystemUserConfiguration == null) {
519            Settings.System.getConfiguration(getContext().getContentResolver(),
520                    mSystemUserConfiguration = new Configuration());
521        }
522        return mSystemUserConfiguration;
523    }
524
525    private void putDeviceInDemoMode() {
526        mDeviceInDemoMode = true;
527
528        final String carrierDemoModeSetting =
529                getContext().getString(R.string.config_carrierDemoModeSetting);
530        mIsCarrierDemoMode = !TextUtils.isEmpty(carrierDemoModeSetting)
531                && (Settings.Secure.getInt(getContext().getContentResolver(),
532                        carrierDemoModeSetting, 0) == 1);
533
534        SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1");
535        mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
536    }
537
538    @Override
539    public void onStart() {
540        if (DEBUG) {
541            Slog.d(TAG, "Service starting up");
542        }
543        mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND,
544                false);
545        mHandlerThread.start();
546        mHandler = new MainHandler(mHandlerThread.getLooper());
547        publishLocalService(RetailDemoModeServiceInternal.class, mLocalService);
548    }
549
550    @Override
551    public void onBootPhase(int bootPhase) {
552        switch (bootPhase) {
553            case PHASE_THIRD_PARTY_APPS_CAN_START:
554                mPreloadAppsInstaller = new PreloadAppsInstaller(getContext());
555                mPm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
556                mAmi = LocalServices.getService(ActivityManagerInternal.class);
557                mWakeLock = mPm.newWakeLock(
558                        PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
559                mNm = NotificationManager.from(getContext());
560                mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
561                mCameraManager = (CameraManager) getContext()
562                        .getSystemService(Context.CAMERA_SERVICE);
563                mCameraIdsWithFlash = getCameraIdsWithFlash();
564                SettingsObserver settingsObserver = new SettingsObserver(mHandler);
565                settingsObserver.register();
566                settingsObserver.refreshTimeoutConstants();
567                break;
568            case PHASE_BOOT_COMPLETED:
569                if (UserManager.isDeviceInDemoMode(getContext())) {
570                    putDeviceInDemoMode();
571                    registerBroadcastReceiver();
572                }
573                break;
574        }
575    }
576
577    @Override
578    public void onSwitchUser(int userId) {
579        if (!mDeviceInDemoMode) {
580            return;
581        }
582        if (DEBUG) {
583            Slog.d(TAG, "onSwitchUser: " + userId);
584        }
585        final UserInfo ui = getUserManager().getUserInfo(userId);
586        if (!ui.isDemo()) {
587            Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
588            return;
589        }
590        if (!mIsCarrierDemoMode && !mWakeLock.isHeld()) {
591            mWakeLock.acquire();
592        }
593        mCurrentUserId = userId;
594        mAmi.updatePersistentConfigurationForUser(getSystemUsersConfiguration(), userId);
595
596        turnOffAllFlashLights();
597        muteVolumeStreams();
598        if (!mWifiManager.isWifiEnabled()) {
599            mWifiManager.setWifiEnabled(true);
600        }
601
602        // Disable lock screen for demo users.
603        LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
604        lockPatternUtils.setLockScreenDisabled(true, userId);
605
606        if (!mIsCarrierDemoMode) {
607            // Show reset notification (except in carrier demo mode).
608            mNm.notifyAsUser(TAG, 1, createResetNotification(), UserHandle.of(userId));
609
610            synchronized (mActivityLock) {
611                mUserUntouched = true;
612            }
613            MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, 1);
614            mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
615            mHandler.post(new Runnable() {
616                @Override
617                public void run() {
618                    mPreloadAppsInstaller.installApps(userId);
619                }
620            });
621        }
622    }
623
624    private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
625        private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000;
626
627        @Override
628        public void onUserActivity() {
629            if (!mDeviceInDemoMode || mIsCarrierDemoMode) {
630                return;
631            }
632            long timeOfActivity = SystemClock.uptimeMillis();
633            synchronized (mActivityLock) {
634                if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
635                    return;
636                }
637                mLastUserActivityTime = timeOfActivity;
638                if (mUserUntouched && isDemoLauncherDisabled()) {
639                    Slog.d(TAG, "retail_demo first touch");
640                    mUserUntouched = false;
641                    mFirstUserActivityTime = timeOfActivity;
642                }
643            }
644            mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
645            mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, mUserInactivityTimeout);
646        }
647    };
648}
649