RetailDemoModeService.java revision d912d9357dc2f7c7540c6297b2a2bb9427fb7761
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.util.KeyValueListParser; 62import android.util.Slog; 63import com.android.internal.os.BackgroundThread; 64import com.android.internal.R; 65import com.android.internal.annotations.GuardedBy; 66import com.android.internal.annotations.VisibleForTesting; 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 @VisibleForTesting 86 static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled"; 87 88 private static final int MSG_TURN_SCREEN_ON = 0; 89 private static final int MSG_INACTIVITY_TIME_OUT = 1; 90 private static final int MSG_START_NEW_SESSION = 2; 91 92 private static final long SCREEN_WAKEUP_DELAY = 2500; 93 private static final long USER_INACTIVITY_TIMEOUT_MIN = 10000; 94 private static final long USER_INACTIVITY_TIMEOUT_DEFAULT = 90000; 95 private static final long WARNING_DIALOG_TIMEOUT_DEFAULT = 0; 96 private static final long MILLIS_PER_SECOND = 1000; 97 98 @VisibleForTesting 99 static final int[] VOLUME_STREAMS_TO_MUTE = { 100 AudioSystem.STREAM_RING, 101 AudioSystem.STREAM_MUSIC 102 }; 103 104 // Tron Vars 105 private static final String DEMO_SESSION_COUNT = "retail_demo_session_count"; 106 private static final String DEMO_SESSION_DURATION = "retail_demo_session_duration"; 107 108 boolean mDeviceInDemoMode = false; 109 int mCurrentUserId = UserHandle.USER_SYSTEM; 110 long mUserInactivityTimeout; 111 long mWarningDialogTimeout; 112 private Injector mInjector; 113 Handler mHandler; 114 private ServiceThread mHandlerThread; 115 private String[] mCameraIdsWithFlash; 116 private PreloadAppsInstaller mPreloadAppsInstaller; 117 118 final Object mActivityLock = new Object(); 119 // Whether the newly created demo user has interacted with the screen yet 120 @GuardedBy("mActivityLock") 121 boolean mUserUntouched; 122 @GuardedBy("mActivityLock") 123 long mFirstUserActivityTime; 124 @GuardedBy("mActivityLock") 125 long mLastUserActivityTime; 126 127 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 128 @Override 129 public void onReceive(Context context, Intent intent) { 130 if (!mDeviceInDemoMode) { 131 return; 132 } 133 switch (intent.getAction()) { 134 case Intent.ACTION_SCREEN_OFF: 135 mHandler.removeMessages(MSG_TURN_SCREEN_ON); 136 mHandler.sendEmptyMessageDelayed(MSG_TURN_SCREEN_ON, SCREEN_WAKEUP_DELAY); 137 break; 138 case ACTION_RESET_DEMO: 139 mHandler.sendEmptyMessage(MSG_START_NEW_SESSION); 140 break; 141 } 142 } 143 }; 144 145 final class MainHandler extends Handler { 146 147 MainHandler(Looper looper) { 148 super(looper, null, true); 149 } 150 151 @Override 152 public void handleMessage(Message msg) { 153 switch (msg.what) { 154 case MSG_TURN_SCREEN_ON: 155 if (mInjector.isWakeLockHeld()) { 156 mInjector.releaseWakeLock(); 157 } 158 mInjector.acquireWakeLock(); 159 break; 160 case MSG_INACTIVITY_TIME_OUT: 161 if (isDemoLauncherDisabled()) { 162 Slog.i(TAG, "User inactivity timeout reached"); 163 showInactivityCountdownDialog(); 164 } 165 break; 166 case MSG_START_NEW_SESSION: 167 if (DEBUG) { 168 Slog.d(TAG, "Switching to a new demo user"); 169 } 170 removeMessages(MSG_START_NEW_SESSION); 171 removeMessages(MSG_INACTIVITY_TIME_OUT); 172 if (mCurrentUserId != UserHandle.USER_SYSTEM) { 173 logSessionDuration(); 174 } 175 final UserInfo demoUser = mInjector.getUserManager().createUser(DEMO_USER_NAME, 176 UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL); 177 if (demoUser != null) { 178 setupDemoUser(demoUser); 179 mInjector.switchUser(demoUser.id); 180 } 181 break; 182 } 183 } 184 } 185 186 @VisibleForTesting 187 class SettingsObserver extends ContentObserver { 188 189 private final static String KEY_USER_INACTIVITY_TIMEOUT = "user_inactivity_timeout_ms"; 190 private final static String KEY_WARNING_DIALOG_TIMEOUT = "warning_dialog_timeout_ms"; 191 192 private final Uri mDeviceDemoModeUri = Settings.Global 193 .getUriFor(Settings.Global.DEVICE_DEMO_MODE); 194 private final Uri mDeviceProvisionedUri = Settings.Global 195 .getUriFor(Settings.Global.DEVICE_PROVISIONED); 196 private final Uri mRetailDemoConstantsUri = Settings.Global 197 .getUriFor(Settings.Global.RETAIL_DEMO_MODE_CONSTANTS); 198 199 private final KeyValueListParser mParser = new KeyValueListParser(','); 200 201 public SettingsObserver(Handler handler) { 202 super(handler); 203 } 204 205 public void register() { 206 ContentResolver cr = mInjector.getContentResolver(); 207 cr.registerContentObserver(mDeviceDemoModeUri, false, this, UserHandle.USER_SYSTEM); 208 cr.registerContentObserver(mDeviceProvisionedUri, false, this, UserHandle.USER_SYSTEM); 209 cr.registerContentObserver(mRetailDemoConstantsUri, false, this, 210 UserHandle.USER_SYSTEM); 211 } 212 213 @Override 214 public void onChange(boolean selfChange, Uri uri) { 215 if (mRetailDemoConstantsUri.equals(uri)) { 216 refreshTimeoutConstants(); 217 return; 218 } 219 if (mDeviceDemoModeUri.equals(uri)) { 220 mDeviceInDemoMode = UserManager.isDeviceInDemoMode(getContext()); 221 if (mDeviceInDemoMode) { 222 putDeviceInDemoMode(); 223 } else { 224 mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0"); 225 if (mInjector.isWakeLockHeld()) { 226 mInjector.releaseWakeLock(); 227 } 228 } 229 } 230 // If device is provisioned and left demo mode - run the cleanup in demo folder 231 if (!mDeviceInDemoMode && isDeviceProvisioned()) { 232 // Run on the bg thread to not block the fg thread 233 BackgroundThread.getHandler().post(new Runnable() { 234 @Override 235 public void run() { 236 if (!deletePreloadsFolderContents()) { 237 Slog.w(TAG, "Failed to delete preloads folder contents"); 238 } 239 } 240 }); 241 } 242 } 243 244 private void refreshTimeoutConstants() { 245 try { 246 mParser.setString(Settings.Global.getString(mInjector.getContentResolver(), 247 Settings.Global.RETAIL_DEMO_MODE_CONSTANTS)); 248 } catch (IllegalArgumentException exc) { 249 Slog.e(TAG, "Invalid string passed to KeyValueListParser"); 250 // Consuming the exception to fall back to default values. 251 } 252 mWarningDialogTimeout = mParser.getLong(KEY_WARNING_DIALOG_TIMEOUT, 253 WARNING_DIALOG_TIMEOUT_DEFAULT); 254 mUserInactivityTimeout = mParser.getLong(KEY_USER_INACTIVITY_TIMEOUT, 255 USER_INACTIVITY_TIMEOUT_DEFAULT); 256 mUserInactivityTimeout = Math.max(mUserInactivityTimeout, USER_INACTIVITY_TIMEOUT_MIN); 257 } 258 } 259 260 private void showInactivityCountdownDialog() { 261 UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(), 262 mWarningDialogTimeout, MILLIS_PER_SECOND); 263 dialog.setNegativeButtonClickListener(null); 264 dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() { 265 @Override 266 public void onClick(DialogInterface dialog, int which) { 267 mHandler.sendEmptyMessage(MSG_START_NEW_SESSION); 268 } 269 }); 270 dialog.setOnCountDownExpiredListener(new OnCountDownExpiredListener() { 271 @Override 272 public void onCountDownExpired() { 273 mHandler.sendEmptyMessage(MSG_START_NEW_SESSION); 274 } 275 }); 276 dialog.show(); 277 } 278 279 public RetailDemoModeService(Context context) { 280 this(new Injector(context)); 281 } 282 283 @VisibleForTesting 284 RetailDemoModeService(Injector injector) { 285 super(injector.getContext()); 286 287 mInjector = injector; 288 synchronized (mActivityLock) { 289 mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis(); 290 } 291 } 292 293 boolean isDemoLauncherDisabled() { 294 IPackageManager pm = mInjector.getIPackageManager(); 295 int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 296 String demoLauncherComponent = getContext().getResources() 297 .getString(R.string.config_demoModeLauncherComponent); 298 try { 299 enabledState = pm.getComponentEnabledSetting( 300 ComponentName.unflattenFromString(demoLauncherComponent), 301 mCurrentUserId); 302 } catch (RemoteException exc) { 303 Slog.e(TAG, "Unable to talk to Package Manager", exc); 304 } 305 return enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 306 } 307 308 private void setupDemoUser(UserInfo userInfo) { 309 UserManager um = mInjector.getUserManager(); 310 UserHandle user = UserHandle.of(userInfo.id); 311 um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user); 312 um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user); 313 um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user); 314 um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user); 315 um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user); 316 um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user); 317 // Set this to false because the default is true on user creation 318 um.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user); 319 // Disallow rebooting in safe mode - controlled by user 0 320 um.setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM); 321 Settings.Secure.putIntForUser(mInjector.getContentResolver(), 322 Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id); 323 Settings.Global.putInt(mInjector.getContentResolver(), 324 Settings.Global.PACKAGE_VERIFIER_ENABLE, 0); 325 326 grantRuntimePermissionToCamera(user); 327 clearPrimaryCallLog(); 328 } 329 330 private void grantRuntimePermissionToCamera(UserHandle user) { 331 final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 332 final PackageManager pm = mInjector.getPackageManager(); 333 final ResolveInfo handler = pm.resolveActivityAsUser(cameraIntent, 334 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 335 user.getIdentifier()); 336 if (handler == null || handler.activityInfo == null) { 337 return; 338 } 339 try { 340 pm.grantRuntimePermission(handler.activityInfo.packageName, 341 Manifest.permission.ACCESS_FINE_LOCATION, user); 342 } catch (Exception e) { 343 // Ignore 344 } 345 } 346 347 private void clearPrimaryCallLog() { 348 final ContentResolver resolver = mInjector.getContentResolver(); 349 350 // Deleting primary user call log so that it doesn't get copied to the new demo user 351 final Uri uri = CallLog.Calls.CONTENT_URI; 352 try { 353 resolver.delete(uri, null, null); 354 } catch (Exception e) { 355 Slog.w(TAG, "Deleting call log failed: " + e); 356 } 357 } 358 359 void logSessionDuration() { 360 final int sessionDuration; 361 synchronized (mActivityLock) { 362 sessionDuration = (int) ((mLastUserActivityTime - mFirstUserActivityTime) / 1000); 363 } 364 mInjector.logSessionDuration(sessionDuration); 365 } 366 367 private boolean isDeviceProvisioned() { 368 return Settings.Global.getInt( 369 mInjector.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; 370 } 371 372 private boolean deletePreloadsFolderContents() { 373 final File dir = mInjector.getDataPreloadsDirectory(); 374 Slog.i(TAG, "Deleting contents of " + dir); 375 return FileUtils.deleteContents(dir); 376 } 377 378 private void registerBroadcastReceiver() { 379 final IntentFilter filter = new IntentFilter(); 380 filter.addAction(Intent.ACTION_SCREEN_OFF); 381 filter.addAction(ACTION_RESET_DEMO); 382 getContext().registerReceiver(mBroadcastReceiver, filter); 383 } 384 385 private String[] getCameraIdsWithFlash() { 386 ArrayList<String> cameraIdsList = new ArrayList<String>(); 387 final CameraManager cm = mInjector.getCameraManager(); 388 if (cm != null) { 389 try { 390 for (String cameraId : cm.getCameraIdList()) { 391 CameraCharacteristics c = cm.getCameraCharacteristics(cameraId); 392 if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) { 393 cameraIdsList.add(cameraId); 394 } 395 } 396 } catch (CameraAccessException e) { 397 Slog.e(TAG, "Unable to access camera while getting camera id list", e); 398 } 399 } 400 return cameraIdsList.toArray(new String[cameraIdsList.size()]); 401 } 402 403 private void muteVolumeStreams() { 404 for (int stream : VOLUME_STREAMS_TO_MUTE) { 405 mInjector.getAudioManager().setStreamVolume(stream, 406 mInjector.getAudioManager().getStreamMinVolume(stream), 0); 407 } 408 } 409 410 private void putDeviceInDemoMode() { 411 mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1"); 412 mHandler.sendEmptyMessage(MSG_START_NEW_SESSION); 413 } 414 415 @Override 416 public void onStart() { 417 if (DEBUG) { 418 Slog.d(TAG, "Service starting up"); 419 } 420 mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, 421 false); 422 mHandlerThread.start(); 423 mHandler = new MainHandler(mHandlerThread.getLooper()); 424 publishLocalService(RetailDemoModeServiceInternal.class, mLocalService); 425 } 426 427 @Override 428 public void onBootPhase(int bootPhase) { 429 switch (bootPhase) { 430 case PHASE_THIRD_PARTY_APPS_CAN_START: 431 mPreloadAppsInstaller = mInjector.getPreloadAppsInstaller(); 432 mInjector.initializeWakeLock(); 433 mCameraIdsWithFlash = getCameraIdsWithFlash(); 434 SettingsObserver settingsObserver = new SettingsObserver(mHandler); 435 settingsObserver.register(); 436 settingsObserver.refreshTimeoutConstants(); 437 registerBroadcastReceiver(); 438 break; 439 case PHASE_BOOT_COMPLETED: 440 if (UserManager.isDeviceInDemoMode(getContext())) { 441 mDeviceInDemoMode = true; 442 putDeviceInDemoMode(); 443 } 444 break; 445 } 446 } 447 448 @Override 449 public void onSwitchUser(int userId) { 450 if (!mDeviceInDemoMode) { 451 return; 452 } 453 if (DEBUG) { 454 Slog.d(TAG, "onSwitchUser: " + userId); 455 } 456 final UserInfo ui = mInjector.getUserManager().getUserInfo(userId); 457 if (!ui.isDemo()) { 458 Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode"); 459 return; 460 } 461 if (!mInjector.isWakeLockHeld()) { 462 mInjector.acquireWakeLock(); 463 } 464 mCurrentUserId = userId; 465 mInjector.getActivityManagerInternal().updatePersistentConfigurationForUser( 466 mInjector.getSystemUsersConfiguration(), userId); 467 mInjector.turnOffAllFlashLights(mCameraIdsWithFlash); 468 muteVolumeStreams(); 469 if (!mInjector.isWifiEnabled()) { 470 mInjector.enableWifi(); 471 } 472 // Disable lock screen for demo users. 473 mInjector.getLockPatternUtils().setLockScreenDisabled(true, userId); 474 mInjector.getNotificationManager().notifyAsUser(TAG, 475 1, mInjector.createResetNotification(), UserHandle.of(userId)); 476 477 synchronized (mActivityLock) { 478 mUserUntouched = true; 479 } 480 mInjector.logSessionCount(1); 481 mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT); 482 mHandler.post(new Runnable() { 483 @Override 484 public void run() { 485 mPreloadAppsInstaller.installApps(userId); 486 } 487 }); 488 } 489 490 private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() { 491 private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000; 492 493 @Override 494 public void onUserActivity() { 495 if (!mDeviceInDemoMode) { 496 return; 497 } 498 long timeOfActivity = SystemClock.uptimeMillis(); 499 synchronized (mActivityLock) { 500 if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) { 501 return; 502 } 503 mLastUserActivityTime = timeOfActivity; 504 if (mUserUntouched && isDemoLauncherDisabled()) { 505 Slog.d(TAG, "retail_demo first touch"); 506 mUserUntouched = false; 507 mFirstUserActivityTime = timeOfActivity; 508 } 509 } 510 mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT); 511 mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, mUserInactivityTimeout); 512 } 513 }; 514 515 static class Injector { 516 private Context mContext; 517 private UserManager mUm; 518 private PackageManager mPm; 519 private NotificationManager mNm; 520 private ActivityManagerService mAms; 521 private ActivityManagerInternal mAmi; 522 private AudioManager mAudioManager; 523 private PowerManager mPowerManager; 524 private CameraManager mCameraManager; 525 private PowerManager.WakeLock mWakeLock; 526 private WifiManager mWifiManager; 527 private Configuration mSystemUserConfiguration; 528 private PendingIntent mResetDemoPendingIntent; 529 530 Injector(Context context) { 531 mContext = context; 532 } 533 534 Context getContext() { 535 return mContext; 536 } 537 538 private WifiManager getWifiManager() { 539 if (mWifiManager == null) { 540 mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 541 } 542 return mWifiManager; 543 } 544 545 UserManager getUserManager() { 546 if (mUm == null) { 547 mUm = getContext().getSystemService(UserManager.class); 548 } 549 return mUm; 550 } 551 552 void switchUser(int userId) { 553 if (mAms == null) { 554 mAms = (ActivityManagerService) ActivityManagerNative.getDefault(); 555 } 556 mAms.switchUser(userId); 557 } 558 559 AudioManager getAudioManager() { 560 if (mAudioManager == null) { 561 mAudioManager = getContext().getSystemService(AudioManager.class); 562 } 563 return mAudioManager; 564 } 565 566 private PowerManager getPowerManager() { 567 if (mPowerManager == null) { 568 mPowerManager = (PowerManager) getContext().getSystemService( 569 Context.POWER_SERVICE); 570 } 571 return mPowerManager; 572 } 573 574 NotificationManager getNotificationManager() { 575 if (mNm == null) { 576 mNm = NotificationManager.from(getContext()); 577 } 578 return mNm; 579 } 580 581 ActivityManagerInternal getActivityManagerInternal() { 582 if (mAmi == null) { 583 mAmi = LocalServices.getService(ActivityManagerInternal.class); 584 } 585 return mAmi; 586 } 587 588 CameraManager getCameraManager() { 589 if (mCameraManager == null) { 590 mCameraManager = (CameraManager) getContext().getSystemService( 591 Context.CAMERA_SERVICE); 592 } 593 return mCameraManager; 594 } 595 596 PackageManager getPackageManager() { 597 if (mPm == null) { 598 mPm = getContext().getPackageManager(); 599 } 600 return mPm; 601 } 602 603 IPackageManager getIPackageManager() { 604 return AppGlobals.getPackageManager(); 605 } 606 607 ContentResolver getContentResolver() { 608 return getContext().getContentResolver(); 609 } 610 611 PreloadAppsInstaller getPreloadAppsInstaller() { 612 return new PreloadAppsInstaller(getContext()); 613 } 614 615 void systemPropertiesSet(String key, String value) { 616 SystemProperties.set(key, value); 617 } 618 619 void turnOffAllFlashLights(String[] cameraIdsWithFlash) { 620 for (String cameraId : cameraIdsWithFlash) { 621 try { 622 getCameraManager().setTorchMode(cameraId, false); 623 } catch (CameraAccessException e) { 624 Slog.e(TAG, "Unable to access camera " + cameraId 625 + " while turning off flash", e); 626 } 627 } 628 } 629 630 void initializeWakeLock() { 631 mWakeLock = getPowerManager().newWakeLock( 632 PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG); 633 } 634 635 boolean isWakeLockHeld() { 636 return mWakeLock.isHeld(); 637 } 638 639 void acquireWakeLock() { 640 mWakeLock.acquire(); 641 } 642 643 void releaseWakeLock() { 644 mWakeLock.release(); 645 } 646 647 boolean isWifiEnabled() { 648 return getWifiManager().isWifiEnabled(); 649 } 650 651 void enableWifi() { 652 getWifiManager().setWifiEnabled(true); 653 } 654 655 void logSessionDuration(int duration) { 656 MetricsLogger.histogram(getContext(), DEMO_SESSION_DURATION, duration); 657 } 658 659 void logSessionCount(int count) { 660 MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, count); 661 } 662 663 Configuration getSystemUsersConfiguration() { 664 if (mSystemUserConfiguration == null) { 665 Settings.System.getConfiguration(getContentResolver(), 666 mSystemUserConfiguration = new Configuration()); 667 } 668 return mSystemUserConfiguration; 669 } 670 671 LockPatternUtils getLockPatternUtils() { 672 return new LockPatternUtils(getContext()); 673 } 674 675 Notification createResetNotification() { 676 return new Notification.Builder(getContext()) 677 .setContentTitle(getContext().getString(R.string.reset_retail_demo_mode_title)) 678 .setContentText(getContext().getString(R.string.reset_retail_demo_mode_text)) 679 .setOngoing(true) 680 .setSmallIcon(R.drawable.platlogo) 681 .setShowWhen(false) 682 .setVisibility(Notification.VISIBILITY_PUBLIC) 683 .setContentIntent(getResetDemoPendingIntent()) 684 .setColor(getContext().getColor(R.color.system_notification_accent_color)) 685 .build(); 686 } 687 688 private PendingIntent getResetDemoPendingIntent() { 689 if (mResetDemoPendingIntent == null) { 690 Intent intent = new Intent(ACTION_RESET_DEMO); 691 mResetDemoPendingIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); 692 } 693 return mResetDemoPendingIntent; 694 } 695 696 File getDataPreloadsDirectory() { 697 return Environment.getDataPreloadsDirectory(); 698 } 699 } 700} 701