Merge "DO NOT MERGE - Remove RetailDemoModeService" into oc-dr1-dev
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d822f96..2d8ed7a 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10080,22 +10080,6 @@
public static final String DEVICE_DEMO_MODE = "device_demo_mode";
/**
- * Retail mode specific settings. This is encoded as a key=value list, separated by commas.
- * Ex: "user_inactivity_timeout_ms=30000,warning_dialog_timeout_ms=10000". The following
- * keys are supported:
- *
- * <pre>
- * user_inactivity_timeout_ms (long)
- * warning_dialog_timeout_ms (long)
- * </pre>
- * <p>
- * Type: string
- *
- * @hide
- */
- public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants";
-
- /**
* Indicates the maximum time that an app is blocked for the network rules to get updated.
*
* Type: long
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index e212c43..fa645f4 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -315,7 +315,6 @@
SettingProto boot_count = 270;
SettingProto safe_boot_disallowed = 271;
SettingProto device_demo_mode = 272;
- SettingProto retail_demo_mode_constants = 273;
SettingProto database_downgrade_reason = 274;
SettingProto contacts_database_wal_enabled = 275;
SettingProto multi_sim_voice_call_subscription = 276;
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bd8e14ea..34710fc 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4590,22 +4590,10 @@
<!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
<string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
- <!-- Title of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
- <string name="reset_retail_demo_mode_title">Reset device?</string>
- <!-- Text of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
- <string name="reset_retail_demo_mode_text">Tap to reset device</string>
<!-- Text of dialog shown when starting a demo user for the first time [CHAR LIMIT=40] -->
<string name="demo_starting_message">Starting demo\u2026</string>
<!-- Text of dialog shown when starting a new demo user in retail demo mode [CHAR LIMIT=40] -->
<string name="demo_restarting_message">Resetting device\u2026</string>
- <!-- Title of the dialog shown when user inactivity times out in retail demo mode [CHAR LIMIT=40] -->
- <string name="demo_user_inactivity_timeout_title">Reset device?</string>
- <!-- Warning message shown when user inactivity times out in retail demo mode [CHAR LIMIT=none] -->
- <string name="demo_user_inactivity_timeout_countdown">You\u2019ll lose any changes and the demo will start again in <xliff:g id="timeout" example="9">%1$s</xliff:g> seconds\u2026</string>
- <!-- Text of button to allow user to abort countdown and continue current session in retail demo mode [CHAR LIMIT=40] -->
- <string name="demo_user_inactivity_timeout_left_button">Cancel</string>
- <!-- Text of button to allow user to abort countdown and immediately start another session in retail demo mode [CHAR LIMIT=40] -->
- <string name="demo_user_inactivity_timeout_right_button">Reset now</string>
<!-- Accessibilty string added to a widget that has been suspended [CHAR LIMIT=20] -->
<string name="suspended_widget_accessibility">Disabled <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ca53885..a979ac8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -298,7 +298,6 @@
Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
- Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
Settings.Global.SAFE_BOOT_DISALLOWED,
Settings.Global.SAMPLING_PROFILER_MS,
Settings.Global.SELINUX_STATUS,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index b328933..819ee3e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -915,9 +915,6 @@
Settings.Global.DEVICE_DEMO_MODE,
GlobalSettingsProto.DEVICE_DEMO_MODE);
dumpSetting(s, p,
- Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
- GlobalSettingsProto.RETAIL_DEMO_MODE_CONSTANTS);
- dumpSetting(s, p,
Settings.Global.DATABASE_DOWNGRADE_REASON,
GlobalSettingsProto.DATABASE_DOWNGRADE_REASON);
dumpSetting(s, p,
diff --git a/services/Android.mk b/services/Android.mk
index 5c863b0..c376470 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -34,7 +34,6 @@
net \
print \
restrictions \
- retaildemo \
usage \
usb \
voiceinteraction
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a94484a..50f4f24 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -53,6 +53,7 @@
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -197,6 +198,9 @@
// System property indicating that the screen should remain off until an explicit user action
private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
+ // System Property indicating that retail demo mode is currently enabled.
+ private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
+
// Possible reasons for shutting down for use in data/misc/reboot/last_shutdown_reason
private static final String REASON_SHUTDOWN = "shutdown";
private static final String REASON_REBOOT = "reboot";
@@ -805,6 +809,9 @@
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DOUBLE_TAP_TO_WAKE),
false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.DEVICE_DEMO_MODE),
+ false, mSettingsObserver, UserHandle.USER_SYSTEM);
IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
if (vrManager != null) {
try {
@@ -912,6 +919,11 @@
}
}
+ final String retailDemoValue = UserManager.isDeviceInDemoMode(mContext) ? "1" : "0";
+ if (!retailDemoValue.equals(SystemProperties.get(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED))) {
+ SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, retailDemoValue);
+ }
+
final int oldScreenBrightnessSetting = getCurrentBrightnessSettingLocked();
mScreenBrightnessForVrSetting = Settings.System.getIntForUser(resolver,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c9be3a2..a902a19 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -100,7 +100,6 @@
import com.android.server.power.ShutdownThread;
import com.android.server.radio.RadioService;
import com.android.server.restrictions.RestrictionsManagerService;
-import com.android.server.retaildemo.RetailDemoModeService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
import com.android.server.soundtrigger.SoundTriggerService;
@@ -1551,10 +1550,6 @@
mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
traceEnd();
- traceBeginAndSlog("StartRetailDemoModeService");
- mSystemServiceManager.startService(RetailDemoModeService.class);
- traceEnd();
-
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOFILL)) {
traceBeginAndSlog("StartAutoFillService");
mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
diff --git a/services/profile-classes b/services/profile-classes
index b0d2da7..289b113 100644
--- a/services/profile-classes
+++ b/services/profile-classes
@@ -5085,11 +5085,6 @@
Lcom/android/server/RescueParty$Threshold;
Lcom/android/server/restrictions/RestrictionsManagerService;
Lcom/android/server/restrictions/RestrictionsManagerService$RestrictionsManagerImpl;
-Lcom/android/server/retaildemo/RetailDemoModeService;
-Lcom/android/server/retaildemo/RetailDemoModeService$1;
-Lcom/android/server/retaildemo/RetailDemoModeService$Injector;
-Lcom/android/server/retaildemo/RetailDemoModeService$MainHandler;
-Lcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;
Lcom/android/server/SamplingProfilerService;
Lcom/android/server/SamplingProfilerService$1;
Lcom/android/server/SamplingProfilerService$SamplingProfilerSettingsObserver;
diff --git a/services/retaildemo/Android.mk b/services/retaildemo/Android.mk
deleted file mode 100644
index 670c6bf..0000000
--- a/services/retaildemo/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.retaildemo
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
deleted file mode 100644
index 90c58d0..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2016 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
- */
-
-package com.android.server.retaildemo;
-
-import android.app.AppGlobals;
-import android.app.PackageInstallObserver;
-import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * Helper class for installing preloaded APKs
- */
-class PreloadAppsInstaller {
- private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
- private static String TAG = PreloadAppsInstaller.class.getSimpleName();
- private static final String PRELOAD_APK_EXT = ".apk.preload";
- private static boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private final IPackageManager mPackageManager;
- private final File preloadsAppsDirectory;
- private final Context mContext;
-
- private final Map<String, String> mApkToPackageMap;
-
- PreloadAppsInstaller(Context context) {
- this(context, AppGlobals.getPackageManager(), Environment.getDataPreloadsAppsDirectory());
- }
-
- @VisibleForTesting
- PreloadAppsInstaller(Context context, IPackageManager packageManager, File preloadsAppsDirectory) {
- mContext = context;
- mPackageManager = packageManager;
- mApkToPackageMap = Collections.synchronizedMap(new ArrayMap<>());
- this.preloadsAppsDirectory = preloadsAppsDirectory;
- }
-
- void installApps(int userId) {
- File[] files = preloadsAppsDirectory.listFiles();
- AppInstallCounter counter = new AppInstallCounter(mContext, userId);
- if (ArrayUtils.isEmpty(files)) {
- counter.setExpectedAppsCount(0);
- return;
- }
- int expectedCount = 0;
- for (File file : files) {
- String apkName = file.getName();
- if (apkName.endsWith(PRELOAD_APK_EXT) && file.isFile()) {
- String packageName = mApkToPackageMap.get(apkName);
- if (packageName != null) {
- try {
- expectedCount++;
- installExistingPackage(packageName, userId, counter);
- } catch (Exception e) {
- Slog.e(TAG, "Failed to install existing package " + packageName, e);
- }
- } else {
- try {
- installPackage(file, userId, counter);
- expectedCount++;
- } catch (Exception e) {
- Slog.e(TAG, "Failed to install package from " + file, e);
- }
- }
- }
- }
- counter.setExpectedAppsCount(expectedCount);
- }
-
- private void installExistingPackage(String packageName, int userId,
- AppInstallCounter counter) {
- if (DEBUG) {
- Log.d(TAG, "installExistingPackage " + packageName + " u" + userId);
- }
- try {
- mPackageManager.installExistingPackageAsUser(packageName, userId,
- 0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } finally {
- counter.appInstallFinished();
- }
- }
-
- private void installPackage(File file, final int userId, AppInstallCounter counter)
- throws IOException, RemoteException {
- final String apkName = file.getName();
- if (DEBUG) {
- Log.d(TAG, "installPackage " + apkName + " u" + userId);
- }
- mPackageManager.installPackageAsUser(file.getPath(), new PackageInstallObserver() {
- @Override
- public void onPackageInstalled(String basePackageName, int returnCode, String msg,
- Bundle extras) {
- if (DEBUG) {
- Log.d(TAG, "Package " + basePackageName + " installed u" + userId
- + " returnCode: " + returnCode + " msg: " + msg);
- }
- // Don't notify the counter for now, we'll do it in installExistingPackage
- if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
- mApkToPackageMap.put(apkName, basePackageName);
- // Install on user 0 so that the package is cached when demo user is re-created
- installExistingPackage(basePackageName, UserHandle.USER_SYSTEM, counter);
- } else if (returnCode == PackageManager.INSTALL_FAILED_ALREADY_EXISTS) {
- // This can only happen in first session after a reboot
- if (!mApkToPackageMap.containsKey(apkName)) {
- mApkToPackageMap.put(apkName, basePackageName);
- }
- installExistingPackage(basePackageName, userId, counter);
- } else {
- Log.e(TAG, "Package " + basePackageName + " cannot be installed from "
- + apkName + ": " + msg + " (returnCode " + returnCode + ")");
- counter.appInstallFinished();
- }
- }
- }.getBinder(), 0, SYSTEM_SERVER_PACKAGE_NAME, userId);
- }
-
- private static class AppInstallCounter {
- private int expectedCount = -1; // -1 means expectedCount not set
- private int finishedCount;
- private final Context mContext;
- private final int userId;
-
- AppInstallCounter(Context context, int userId) {
- mContext = context;
- this.userId = userId;
- }
-
- synchronized void appInstallFinished() {
- this.finishedCount++;
- checkIfAllFinished();
- }
-
- synchronized void setExpectedAppsCount(int expectedCount) {
- this.expectedCount = expectedCount;
- checkIfAllFinished();
- }
-
- private void checkIfAllFinished() {
- if (expectedCount == finishedCount) {
- Log.i(TAG, "All preloads finished installing for user " + userId);
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, "1", userId);
- }
- }
- }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
deleted file mode 100644
index 711d4d9d..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * Copyright (C) 2016 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
- */
-
-package com.android.server.retaildemo;
-
-import android.Manifest;
-import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
-import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.RetailDemoModeServiceInternal;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.database.ContentObserver;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.media.AudioManager;
-import android.media.AudioSystem;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.KeyValueListParser;
-import android.util.Slog;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.LocalServices;
-import com.android.server.PreloadsFileCacheExpirationJobService;
-import com.android.server.ServiceThread;
-import com.android.server.SystemService;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.retaildemo.UserInactivityCountdownDialog.OnCountDownExpiredListener;
-
-import java.io.File;
-import java.util.ArrayList;
-
-public class RetailDemoModeService extends SystemService {
- private static final boolean DEBUG = false;
-
- private static final String TAG = RetailDemoModeService.class.getSimpleName();
- private static final String DEMO_USER_NAME = "Demo";
- private static final String ACTION_RESET_DEMO =
- "com.android.server.retaildemo.ACTION_RESET_DEMO";
- @VisibleForTesting
- static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
-
- private static final int MSG_TURN_SCREEN_ON = 0;
- private static final int MSG_INACTIVITY_TIME_OUT = 1;
- private static final int MSG_START_NEW_SESSION = 2;
-
- private static final long SCREEN_WAKEUP_DELAY = 2500;
- private static final long USER_INACTIVITY_TIMEOUT_MIN = 10000;
- private static final long USER_INACTIVITY_TIMEOUT_DEFAULT = 90000;
- private static final long WARNING_DIALOG_TIMEOUT_DEFAULT = 0;
- private static final long MILLIS_PER_SECOND = 1000;
-
- @VisibleForTesting
- static final int[] VOLUME_STREAMS_TO_MUTE = {
- AudioSystem.STREAM_RING,
- AudioSystem.STREAM_MUSIC
- };
-
- // Tron Vars
- private static final String DEMO_SESSION_COUNT = "retail_demo_session_count";
- private static final String DEMO_SESSION_DURATION = "retail_demo_session_duration";
-
- boolean mDeviceInDemoMode;
- boolean mIsCarrierDemoMode;
- int mCurrentUserId = UserHandle.USER_SYSTEM;
- long mUserInactivityTimeout;
- long mWarningDialogTimeout;
- private Injector mInjector;
- Handler mHandler;
- private ServiceThread mHandlerThread;
- private String[] mCameraIdsWithFlash;
- private PreloadAppsInstaller mPreloadAppsInstaller;
-
- final Object mActivityLock = new Object();
- // Whether the newly created demo user has interacted with the screen yet
- @GuardedBy("mActivityLock")
- boolean mUserUntouched;
- @GuardedBy("mActivityLock")
- long mFirstUserActivityTime;
- @GuardedBy("mActivityLock")
- long mLastUserActivityTime;
-
- private boolean mSafeBootRestrictionInitialState;
- private int mPackageVerifierEnableInitialState;
-
- private IntentReceiver mBroadcastReceiver = null;
-
- private final class IntentReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!mDeviceInDemoMode) {
- return;
- }
- final String action = intent.getAction();
- switch (action) {
- case Intent.ACTION_SCREEN_OFF:
- mHandler.removeMessages(MSG_TURN_SCREEN_ON);
- mHandler.sendEmptyMessageDelayed(MSG_TURN_SCREEN_ON, SCREEN_WAKEUP_DELAY);
- break;
- case ACTION_RESET_DEMO:
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
- break;
- }
- }
- };
-
- final class MainHandler extends Handler {
-
- MainHandler(Looper looper) {
- super(looper, null, true);
- }
-
- @Override
- public void handleMessage(Message msg) {
- if (!mDeviceInDemoMode) {
- return;
- }
- switch (msg.what) {
- case MSG_TURN_SCREEN_ON:
- if (mInjector.isWakeLockHeld()) {
- mInjector.releaseWakeLock();
- }
- mInjector.acquireWakeLock();
- break;
- case MSG_INACTIVITY_TIME_OUT:
- if (!mIsCarrierDemoMode && isDemoLauncherDisabled()) {
- Slog.i(TAG, "User inactivity timeout reached");
- showInactivityCountdownDialog();
- }
- break;
- case MSG_START_NEW_SESSION:
- if (DEBUG) {
- Slog.d(TAG, "Switching to a new demo user");
- }
- removeMessages(MSG_START_NEW_SESSION);
- removeMessages(MSG_INACTIVITY_TIME_OUT);
- if (!mIsCarrierDemoMode && mCurrentUserId != UserHandle.USER_SYSTEM) {
- logSessionDuration();
- }
-
- final UserManager um = mInjector.getUserManager();
- UserInfo demoUser = null;
- if (mIsCarrierDemoMode) {
- // Re-use the existing demo user in carrier demo mode.
- for (UserInfo user : um.getUsers()) {
- if (user.isDemo()) {
- demoUser = user;
- break;
- }
- }
- }
-
- if (demoUser == null) {
- // User in carrier demo mode should survive reboots.
- final int flags = UserInfo.FLAG_DEMO
- | (mIsCarrierDemoMode ? 0 : UserInfo.FLAG_EPHEMERAL);
- demoUser = um.createUser(DEMO_USER_NAME, flags);
- }
-
- if (demoUser != null && mCurrentUserId != demoUser.id) {
- setupDemoUser(demoUser);
- mInjector.switchUser(demoUser.id);
- }
- break;
- }
- }
- }
-
- @VisibleForTesting
- class SettingsObserver extends ContentObserver {
-
- private final static String KEY_USER_INACTIVITY_TIMEOUT = "user_inactivity_timeout_ms";
- private final static String KEY_WARNING_DIALOG_TIMEOUT = "warning_dialog_timeout_ms";
-
- private final Uri mDeviceDemoModeUri = Settings.Global
- .getUriFor(Settings.Global.DEVICE_DEMO_MODE);
- private final Uri mDeviceProvisionedUri = Settings.Global
- .getUriFor(Settings.Global.DEVICE_PROVISIONED);
- private final Uri mRetailDemoConstantsUri = Settings.Global
- .getUriFor(Settings.Global.RETAIL_DEMO_MODE_CONSTANTS);
-
- private final KeyValueListParser mParser = new KeyValueListParser(',');
-
- public SettingsObserver(Handler handler) {
- super(handler);
- }
-
- public void register() {
- final ContentResolver cr = mInjector.getContentResolver();
- cr.registerContentObserver(mDeviceDemoModeUri, false, this, UserHandle.USER_SYSTEM);
- cr.registerContentObserver(mDeviceProvisionedUri, false, this, UserHandle.USER_SYSTEM);
- cr.registerContentObserver(mRetailDemoConstantsUri, false, this,
- UserHandle.USER_SYSTEM);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (mRetailDemoConstantsUri.equals(uri)) {
- refreshTimeoutConstants();
- return;
- }
-
- // If device is provisioned and left demo mode - run the cleanup in demo folder
- if (isDeviceProvisioned()) {
- if (UserManager.isDeviceInDemoMode(getContext())) {
- startDemoMode();
- } else {
- mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0");
-
- // Run on the bg thread to not block the fg thread
- BackgroundThread.getHandler().post(() -> {
- if (!deletePreloadsFolderContents()) {
- Slog.w(TAG, "Failed to delete preloads folder contents");
- }
- PreloadsFileCacheExpirationJobService.schedule(mInjector.getContext());
- });
-
- stopDemoMode();
-
- if (mInjector.isWakeLockHeld()) {
- mInjector.releaseWakeLock();
- }
- }
- }
- }
-
- private void refreshTimeoutConstants() {
- try {
- mParser.setString(Settings.Global.getString(mInjector.getContentResolver(),
- Settings.Global.RETAIL_DEMO_MODE_CONSTANTS));
- } catch (IllegalArgumentException exc) {
- Slog.e(TAG, "Invalid string passed to KeyValueListParser");
- // Consuming the exception to fall back to default values.
- }
- mWarningDialogTimeout = mParser.getLong(KEY_WARNING_DIALOG_TIMEOUT,
- WARNING_DIALOG_TIMEOUT_DEFAULT);
- mUserInactivityTimeout = mParser.getLong(KEY_USER_INACTIVITY_TIMEOUT,
- USER_INACTIVITY_TIMEOUT_DEFAULT);
- mUserInactivityTimeout = Math.max(mUserInactivityTimeout, USER_INACTIVITY_TIMEOUT_MIN);
- }
- }
-
- private void showInactivityCountdownDialog() {
- UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
- mWarningDialogTimeout, MILLIS_PER_SECOND);
- dialog.setNegativeButtonClickListener(null);
- dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
- }
- });
- dialog.setOnCountDownExpiredListener(new OnCountDownExpiredListener() {
- @Override
- public void onCountDownExpired() {
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
- }
- });
- dialog.show();
- }
-
- public RetailDemoModeService(Context context) {
- this(new Injector(context));
- }
-
- @VisibleForTesting
- RetailDemoModeService(Injector injector) {
- super(injector.getContext());
-
- mInjector = injector;
- synchronized (mActivityLock) {
- mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis();
- }
- }
-
- boolean isDemoLauncherDisabled() {
- int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- try {
- final IPackageManager iPm = mInjector.getIPackageManager();
- final String demoLauncherComponent =
- getContext().getString(R.string.config_demoModeLauncherComponent);
- enabledState = iPm.getComponentEnabledSetting(
- ComponentName.unflattenFromString(demoLauncherComponent), mCurrentUserId);
- } catch (RemoteException re) {
- Slog.e(TAG, "Error retrieving demo launcher enabled setting", re);
- }
- return enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
- }
-
- private void setupDemoUser(UserInfo userInfo) {
- final UserManager um = mInjector.getUserManager();
- final UserHandle user = UserHandle.of(userInfo.id);
- um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
- um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
- um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
- um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
- um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
- um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
- // Set this to false because the default is true on user creation
- um.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
- // Disallow rebooting in safe mode - controlled by user 0
- um.setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
- if (mIsCarrierDemoMode) {
- // Enable SMS in carrier demo mode.
- um.setUserRestriction(UserManager.DISALLOW_SMS, false, user);
- }
-
- Settings.Secure.putIntForUser(mInjector.getContentResolver(),
- Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
- Settings.Global.putInt(mInjector.getContentResolver(),
- Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
-
- grantRuntimePermissionToCamera(user);
- clearPrimaryCallLog();
-
- if (!mIsCarrierDemoMode) {
- // Enable demo launcher.
- final String demoLauncher = getContext().getString(
- R.string.config_demoModeLauncherComponent);
- if (!TextUtils.isEmpty(demoLauncher)) {
- final ComponentName componentToEnable =
- ComponentName.unflattenFromString(demoLauncher);
- final String packageName = componentToEnable.getPackageName();
- try {
- final IPackageManager iPm = AppGlobals.getPackageManager();
- iPm.setComponentEnabledSetting(componentToEnable,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id);
- iPm.setApplicationEnabledSetting(packageName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
- } catch (RemoteException re) {
- // Internal, shouldn't happen
- }
- }
- } else {
- // Set the carrier demo mode setting for the demo user.
- final String carrierDemoModeSetting = getContext().getString(
- R.string.config_carrierDemoModeSetting);
- Settings.Secure.putIntForUser(getContext().getContentResolver(),
- carrierDemoModeSetting, 1, userInfo.id);
-
- // Enable packages for carrier demo mode.
- final String packageList = getContext().getString(
- R.string.config_carrierDemoModePackages);
- final String[] packageNames = packageList == null ? new String[0]
- : TextUtils.split(packageList, ",");
- final IPackageManager iPm = AppGlobals.getPackageManager();
- for (String packageName : packageNames) {
- try {
- iPm.setApplicationEnabledSetting(packageName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
- } catch (RemoteException re) {
- Slog.e(TAG, "Error enabling application: " + packageName, re);
- }
- }
- }
- }
-
- private void grantRuntimePermissionToCamera(UserHandle user) {
- final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- final PackageManager pm = mInjector.getPackageManager();
- final ResolveInfo handler = pm.resolveActivityAsUser(cameraIntent,
- PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
- if (handler == null || handler.activityInfo == null) {
- return;
- }
- try {
- pm.grantRuntimePermission(handler.activityInfo.packageName,
- Manifest.permission.ACCESS_FINE_LOCATION, user);
- } catch (Exception e) {
- // Ignore
- }
- }
-
- private void clearPrimaryCallLog() {
- final ContentResolver resolver = mInjector.getContentResolver();
-
- // Deleting primary user call log so that it doesn't get copied to the new demo user
- final Uri uri = CallLog.Calls.CONTENT_URI;
- try {
- resolver.delete(uri, null, null);
- } catch (Exception e) {
- Slog.w(TAG, "Deleting call log failed: " + e);
- }
- }
-
- void logSessionDuration() {
- final int sessionDuration;
- synchronized (mActivityLock) {
- sessionDuration = (int) ((mLastUserActivityTime - mFirstUserActivityTime) / 1000);
- }
- mInjector.logSessionDuration(sessionDuration);
- }
-
- private boolean isDeviceProvisioned() {
- return Settings.Global.getInt(
- mInjector.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- }
-
- /**
- * Deletes contents of {@link Environment#getDataPreloadsDirectory()},
- * but leave {@link Environment#getDataPreloadsFileCacheDirectory()}
- * @return true if contents was sucessfully deleted
- */
- private boolean deletePreloadsFolderContents() {
- final File dir = mInjector.getDataPreloadsDirectory();
- final File[] files = FileUtils.listFilesOrEmpty(dir);
- final File fileCacheDirectory = mInjector.getDataPreloadsFileCacheDirectory();
- Slog.i(TAG, "Deleting contents of " + dir);
- boolean success = true;
- for (File file : files) {
- if (file.isFile()) {
- if (!file.delete()) {
- success = false;
- Slog.w(TAG, "Cannot delete file " + file);
- }
- } else {
- // Do not remove file_cache dir
- if (!file.equals(fileCacheDirectory)) {
- if (!FileUtils.deleteContentsAndDir(file)) {
- success = false;
- Slog.w(TAG, "Cannot delete dir and its content " + file);
- }
- } else {
- Slog.i(TAG, "Skipping directory with file cache " + file);
- }
- }
- }
- return success;
- }
-
- private void registerBroadcastReceiver() {
- if (mBroadcastReceiver != null) {
- return;
- }
-
- final IntentFilter filter = new IntentFilter();
- if (!mIsCarrierDemoMode) {
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- }
- filter.addAction(ACTION_RESET_DEMO);
- mBroadcastReceiver = new IntentReceiver();
- getContext().registerReceiver(mBroadcastReceiver, filter);
- }
-
- private void unregisterBroadcastReceiver() {
- if (mBroadcastReceiver != null) {
- getContext().unregisterReceiver(mBroadcastReceiver);
- mBroadcastReceiver = null;
- }
- }
-
- private String[] getCameraIdsWithFlash() {
- ArrayList<String> cameraIdsList = new ArrayList<String>();
- final CameraManager cm = mInjector.getCameraManager();
- if (cm != null) {
- try {
- for (String cameraId : cm.getCameraIdList()) {
- CameraCharacteristics c = cm.getCameraCharacteristics(cameraId);
- if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) {
- cameraIdsList.add(cameraId);
- }
- }
- } catch (CameraAccessException e) {
- Slog.e(TAG, "Unable to access camera while getting camera id list", e);
- }
- }
- return cameraIdsList.toArray(new String[cameraIdsList.size()]);
- }
-
- private void muteVolumeStreams() {
- for (int stream : VOLUME_STREAMS_TO_MUTE) {
- mInjector.getAudioManager().setStreamVolume(stream,
- mInjector.getAudioManager().getStreamMinVolume(stream), 0);
- }
- }
-
- private void startDemoMode() {
- mDeviceInDemoMode = true;
-
- mPreloadAppsInstaller = mInjector.getPreloadAppsInstaller();
- mInjector.initializeWakeLock();
- if (mCameraIdsWithFlash == null) {
- mCameraIdsWithFlash = getCameraIdsWithFlash();
- }
- registerBroadcastReceiver();
-
- final String carrierDemoModeSetting =
- getContext().getString(R.string.config_carrierDemoModeSetting);
- mIsCarrierDemoMode = !TextUtils.isEmpty(carrierDemoModeSetting)
- && (Settings.Secure.getInt(getContext().getContentResolver(),
- carrierDemoModeSetting, 0) == 1);
-
- mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1");
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-
- mSafeBootRestrictionInitialState = mInjector.getUserManager().hasUserRestriction(
- UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM);
- mPackageVerifierEnableInitialState = Settings.Global.getInt(mInjector.getContentResolver(),
- Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
- }
-
- private void stopDemoMode() {
- mPreloadAppsInstaller = null;
- mCameraIdsWithFlash = null;
- mInjector.destroyWakeLock();
- unregisterBroadcastReceiver();
-
- if (mDeviceInDemoMode) {
- mInjector.getUserManager().setUserRestriction(UserManager.DISALLOW_SAFE_BOOT,
- mSafeBootRestrictionInitialState, UserHandle.SYSTEM);
- Settings.Global.putInt(mInjector.getContentResolver(),
- Settings.Global.PACKAGE_VERIFIER_ENABLE,
- mPackageVerifierEnableInitialState);
- }
-
- mDeviceInDemoMode = false;
- mIsCarrierDemoMode = false;
- }
-
- @Override
- public void onStart() {
- if (DEBUG) {
- Slog.d(TAG, "Service starting up");
- }
- mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND,
- false);
- mHandlerThread.start();
- mHandler = new MainHandler(mHandlerThread.getLooper());
- mInjector.publishLocalService(this, mLocalService);
- }
-
- @Override
- public void onBootPhase(int bootPhase) {
- switch (bootPhase) {
- case PHASE_THIRD_PARTY_APPS_CAN_START:
- final SettingsObserver settingsObserver = new SettingsObserver(mHandler);
- settingsObserver.register();
- settingsObserver.refreshTimeoutConstants();
- break;
- case PHASE_BOOT_COMPLETED:
- if (UserManager.isDeviceInDemoMode(getContext())) {
- startDemoMode();
- }
- break;
- }
- }
-
- @Override
- public void onSwitchUser(int userId) {
- if (!mDeviceInDemoMode) {
- return;
- }
- if (DEBUG) {
- Slog.d(TAG, "onSwitchUser: " + userId);
- }
- final UserInfo ui = mInjector.getUserManager().getUserInfo(userId);
- if (!ui.isDemo()) {
- Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
- return;
- }
- if (!mIsCarrierDemoMode && !mInjector.isWakeLockHeld()) {
- mInjector.acquireWakeLock();
- }
- mCurrentUserId = userId;
- mInjector.getActivityManagerInternal().updatePersistentConfigurationForUser(
- mInjector.getSystemUsersConfiguration(), userId);
-
- mInjector.turnOffAllFlashLights(mCameraIdsWithFlash);
- muteVolumeStreams();
- if (!mInjector.getWifiManager().isWifiEnabled()) {
- mInjector.getWifiManager().setWifiEnabled(true);
- }
-
- // Disable lock screen for demo users.
- mInjector.getLockPatternUtils().setLockScreenDisabled(true, userId);
-
- if (!mIsCarrierDemoMode) {
- // Show reset notification (except in carrier demo mode).
- mInjector.getNotificationManager().notifyAsUser(TAG, SystemMessage.NOTE_RETAIL_RESET,
- mInjector.createResetNotification(), UserHandle.of(userId));
-
- synchronized (mActivityLock) {
- mUserUntouched = true;
- }
- mInjector.logSessionCount(1);
- mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mPreloadAppsInstaller.installApps(userId);
- }
- });
- }
- }
-
- private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
- private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000;
-
- @Override
- public void onUserActivity() {
- if (!mDeviceInDemoMode || mIsCarrierDemoMode) {
- return;
- }
- long timeOfActivity = SystemClock.uptimeMillis();
- synchronized (mActivityLock) {
- if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
- return;
- }
- mLastUserActivityTime = timeOfActivity;
- if (mUserUntouched && isDemoLauncherDisabled()) {
- Slog.d(TAG, "retail_demo first touch");
- mUserUntouched = false;
- mFirstUserActivityTime = timeOfActivity;
- }
- }
- mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
- mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, mUserInactivityTimeout);
- }
- };
-
- static class Injector {
- private Context mContext;
- private UserManager mUm;
- private PackageManager mPm;
- private NotificationManager mNm;
- private ActivityManagerService mAms;
- private ActivityManagerInternal mAmi;
- private AudioManager mAudioManager;
- private PowerManager mPowerManager;
- private CameraManager mCameraManager;
- private PowerManager.WakeLock mWakeLock;
- private WifiManager mWifiManager;
- private Configuration mSystemUserConfiguration;
- private PendingIntent mResetDemoPendingIntent;
- private PreloadAppsInstaller mPreloadAppsInstaller;
-
- Injector(Context context) {
- mContext = context;
- }
-
- Context getContext() {
- return mContext;
- }
-
- WifiManager getWifiManager() {
- if (mWifiManager == null) {
- mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- }
- return mWifiManager;
- }
-
- UserManager getUserManager() {
- if (mUm == null) {
- mUm = getContext().getSystemService(UserManager.class);
- }
- return mUm;
- }
-
- void switchUser(int userId) {
- if (mAms == null) {
- mAms = (ActivityManagerService) ActivityManager.getService();
- }
- mAms.switchUser(userId);
- }
-
- AudioManager getAudioManager() {
- if (mAudioManager == null) {
- mAudioManager = getContext().getSystemService(AudioManager.class);
- }
- return mAudioManager;
- }
-
- private PowerManager getPowerManager() {
- if (mPowerManager == null) {
- mPowerManager = (PowerManager) getContext().getSystemService(
- Context.POWER_SERVICE);
- }
- return mPowerManager;
- }
-
- NotificationManager getNotificationManager() {
- if (mNm == null) {
- mNm = NotificationManager.from(getContext());
- }
- return mNm;
- }
-
- ActivityManagerInternal getActivityManagerInternal() {
- if (mAmi == null) {
- mAmi = LocalServices.getService(ActivityManagerInternal.class);
- }
- return mAmi;
- }
-
- CameraManager getCameraManager() {
- if (mCameraManager == null) {
- mCameraManager = (CameraManager) getContext().getSystemService(
- Context.CAMERA_SERVICE);
- }
- return mCameraManager;
- }
-
- PackageManager getPackageManager() {
- if (mPm == null) {
- mPm = getContext().getPackageManager();
- }
- return mPm;
- }
-
- IPackageManager getIPackageManager() {
- return AppGlobals.getPackageManager();
- }
-
- ContentResolver getContentResolver() {
- return getContext().getContentResolver();
- }
-
- PreloadAppsInstaller getPreloadAppsInstaller() {
- if (mPreloadAppsInstaller == null) {
- mPreloadAppsInstaller = new PreloadAppsInstaller(getContext());
- }
- return mPreloadAppsInstaller;
- }
-
- void systemPropertiesSet(String key, String value) {
- SystemProperties.set(key, value);
- }
-
- void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
- for (String cameraId : cameraIdsWithFlash) {
- try {
- getCameraManager().setTorchMode(cameraId, false);
- } catch (CameraAccessException e) {
- Slog.e(TAG, "Unable to access camera " + cameraId
- + " while turning off flash", e);
- }
- }
- }
-
- void initializeWakeLock() {
- if (mWakeLock == null) {
- mWakeLock = getPowerManager().newWakeLock(
- PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
- }
- }
-
- void destroyWakeLock() {
- mWakeLock = null;
- }
-
- boolean isWakeLockHeld() {
- return mWakeLock != null && mWakeLock.isHeld();
- }
-
- void acquireWakeLock() {
- mWakeLock.acquire();
- }
-
- void releaseWakeLock() {
- mWakeLock.release();
- }
-
- void logSessionDuration(int duration) {
- MetricsLogger.histogram(getContext(), DEMO_SESSION_DURATION, duration);
- }
-
- void logSessionCount(int count) {
- MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, count);
- }
-
- Configuration getSystemUsersConfiguration() {
- if (mSystemUserConfiguration == null) {
- Settings.System.getConfiguration(getContentResolver(),
- mSystemUserConfiguration = new Configuration());
- }
- return mSystemUserConfiguration;
- }
-
- LockPatternUtils getLockPatternUtils() {
- return new LockPatternUtils(getContext());
- }
-
- Notification createResetNotification() {
- return new Notification.Builder(getContext(), SystemNotificationChannels.RETAIL_MODE)
- .setContentTitle(getContext().getString(R.string.reset_retail_demo_mode_title))
- .setContentText(getContext().getString(R.string.reset_retail_demo_mode_text))
- .setOngoing(true)
- .setSmallIcon(R.drawable.platlogo)
- .setShowWhen(false)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setContentIntent(getResetDemoPendingIntent())
- .setColor(getContext().getColor(R.color.system_notification_accent_color))
- .build();
- }
-
- private PendingIntent getResetDemoPendingIntent() {
- if (mResetDemoPendingIntent == null) {
- Intent intent = new Intent(ACTION_RESET_DEMO);
- mResetDemoPendingIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
- }
- return mResetDemoPendingIntent;
- }
-
- File getDataPreloadsDirectory() {
- return Environment.getDataPreloadsDirectory();
- }
-
- File getDataPreloadsFileCacheDirectory() {
- return Environment.getDataPreloadsFileCacheDirectory();
- }
-
- void publishLocalService(RetailDemoModeService service,
- RetailDemoModeServiceInternal localService) {
- service.publishLocalService(RetailDemoModeServiceInternal.class, localService);
- }
- }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
deleted file mode 100644
index 013eab8..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2016 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
- */
-
-package com.android.server.retaildemo;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.os.CountDownTimer;
-import android.view.WindowManager;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-public class UserInactivityCountdownDialog extends AlertDialog {
-
- private OnCountDownExpiredListener mOnCountDownExpiredListener;
- private CountDownTimer mCountDownTimer;
- private long mCountDownDuration;
- private long mRefreshInterval;
-
- UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) {
- super(context);
- mCountDownDuration = duration;
- mRefreshInterval = refreshInterval;
-
- getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
- WindowManager.LayoutParams attrs = getWindow().getAttributes();
- attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- getWindow().setAttributes(attrs);
-
- setTitle(R.string.demo_user_inactivity_timeout_title);
- setMessage(getContext().getString(R.string.demo_user_inactivity_timeout_countdown,
- duration));
- }
-
- public void setOnCountDownExpiredListener(
- OnCountDownExpiredListener onCountDownExpiredListener) {
- mOnCountDownExpiredListener = onCountDownExpiredListener;
- }
-
- public void setPositiveButtonClickListener(OnClickListener onClickListener) {
- setButton(Dialog.BUTTON_POSITIVE,
- getContext().getString(R.string.demo_user_inactivity_timeout_right_button),
- onClickListener);
- }
-
- public void setNegativeButtonClickListener(OnClickListener onClickListener) {
- setButton(Dialog.BUTTON_NEGATIVE,
- getContext().getString(R.string.demo_user_inactivity_timeout_left_button),
- onClickListener);
- }
-
- @Override
- public void show() {
- super.show();
- final TextView messageView = findViewById(R.id.message);
- messageView.post(new Runnable() {
- @Override
- public void run() {
- mCountDownTimer = new CountDownTimer(mCountDownDuration, mRefreshInterval) {
-
- @Override
- public void onTick(long millisUntilFinished) {
- String msg = getContext().getString(
- R.string.demo_user_inactivity_timeout_countdown,
- millisUntilFinished / 1000);
- messageView.setText(msg);
- }
-
- @Override
- public void onFinish() {
- dismiss();
- if (mOnCountDownExpiredListener != null)
- mOnCountDownExpiredListener.onCountDownExpired();
- }
- }.start();
- }
- });
- }
-
- @Override
- public void onStop() {
- if (mCountDownTimer != null) {
- mCountDownTimer.cancel();
- }
- }
-
- interface OnCountDownExpiredListener {
- void onCountDownExpired();
- }
-}
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index 940db79..79f96fd 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -18,7 +18,6 @@
services.core \
services.devicepolicy \
services.net \
- services.retaildemo \
services.usage \
guava \
android-support-test \
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 2c3283c..e3a6dae 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -19,7 +19,6 @@
services.core \
services.devicepolicy \
services.net \
- services.retaildemo \
services.usage \
guava \
android-support-test \
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
deleted file mode 100644
index cf27a50..0000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-package com.android.server.retaildemo;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.IPackageInstallObserver2;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.FileUtils;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentResolver;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.io.File;
-import java.util.ArrayList;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class PreloadAppsInstallerTest {
- private static final int TEST_DEMO_USER = 111;
-
- private Context mContext;
- private @Mock IPackageManager mIpm;
- private MockContentResolver mContentResolver;
- private File mPreloadsAppsDirectory;
- private String[] mPreloadedApps =
- new String[] {"test1.apk.preload", "test2.apk.preload", "test3.apk.preload"};
- private ArrayList<String> mPreloadedAppPaths = new ArrayList<>();
-
- private PreloadAppsInstaller mInstaller;
-
- @BeforeClass
- @AfterClass
- public static void clearSettingsProvider() {
- FakeSettingsProvider.clearSettingsProvider();
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
- mContentResolver = new MockContentResolver(mContext);
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- when(mContext.getContentResolver()).thenReturn(mContentResolver);
- initializePreloadedApps();
- Settings.Secure.putStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, "0", TEST_DEMO_USER);
-
- mInstaller = new PreloadAppsInstaller(mContext, mIpm, mPreloadsAppsDirectory);
- }
-
- private void initializePreloadedApps() throws Exception {
- mPreloadsAppsDirectory = new File(InstrumentationRegistry.getContext().getFilesDir(),
- "test_preload_apps_dir");
- mPreloadsAppsDirectory.mkdir();
- for (String name : mPreloadedApps) {
- final File f = new File(mPreloadsAppsDirectory, name);
- f.createNewFile();
- mPreloadedAppPaths.add(f.getPath());
- }
- }
-
- @After
- public void tearDown() {
- if (mPreloadsAppsDirectory != null) {
- FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
- }
- }
-
- @Test
- public void testInstallApps() throws Exception {
- mInstaller.installApps(TEST_DEMO_USER);
- for (String path : mPreloadedAppPaths) {
- ArgumentCaptor<IPackageInstallObserver2> observer =
- ArgumentCaptor.forClass(IPackageInstallObserver2.class);
- verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
- anyString(), eq(TEST_DEMO_USER));
- observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
- null, null);
- // Verify that we try to install the package in system user.
- verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
- 0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
- }
- assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
- "1",
- Settings.Secure.getStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
- }
-
- @Test
- public void testInstallApps_noPreloads() throws Exception {
- // Delete all files in preloaded apps directory - no preloaded apps
- FileUtils.deleteContents(mPreloadsAppsDirectory);
- mInstaller.installApps(TEST_DEMO_USER);
- assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
- "1",
- Settings.Secure.getStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
- }
-
- @Test
- public void testInstallApps_installationFails() throws Exception {
- mInstaller.installApps(TEST_DEMO_USER);
- for (int i = 0; i < mPreloadedAppPaths.size(); ++i) {
- ArgumentCaptor<IPackageInstallObserver2> observer =
- ArgumentCaptor.forClass(IPackageInstallObserver2.class);
- final String path = mPreloadedAppPaths.get(i);
- verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
- anyString(), eq(TEST_DEMO_USER));
- if (i == 0) {
- observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_FAILED_DEXOPT,
- null, null);
- continue;
- }
- observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
- null, null);
- // Verify that we try to install the package in system user.
- verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
- 0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
- }
- assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
- "1",
- Settings.Secure.getStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
deleted file mode 100644
index a93f6439..0000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-package com.android.server.retaildemo;
-
-import static com.android.server.retaildemo.RetailDemoModeService.SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.app.ActivityManagerInternal;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.RetailDemoModeServiceInternal;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentProvider;
-import android.test.mock.MockContentResolver;
-import android.util.ArrayMap;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.SystemService;
-import com.android.server.retaildemo.RetailDemoModeService.Injector;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.compat.ArgumentMatcher;
-
-import java.io.File;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class RetailDemoModeServiceTest {
- private static final int TEST_DEMO_USER = 111;
- private static final long SETUP_COMPLETE_TIMEOUT_MS = 2000; // 2 sec
- private static final String TEST_CAMERA_PKG = "test.cameraapp";
- private static final String TEST_PRELOADS_DIR_NAME = "test_preloads";
-
- private Context mContext;
- private @Mock UserManager mUm;
- private @Mock PackageManager mPm;
- private @Mock IPackageManager mIpm;
- private @Mock NotificationManager mNm;
- private @Mock ActivityManagerInternal mAmi;
- private @Mock AudioManager mAudioManager;
- private @Mock WifiManager mWifiManager;
- private @Mock LockPatternUtils mLockPatternUtils;
- private @Mock JobScheduler mJobScheduler;
- private MockPreloadAppsInstaller mPreloadAppsInstaller;
- private MockContentResolver mContentResolver;
- private MockContactsProvider mContactsProvider;
- private Configuration mConfiguration;
- private File mTestPreloadsDir;
- private CountDownLatch mLatch;
-
- private RetailDemoModeService mService;
- private TestInjector mInjector;
-
- @BeforeClass
- @AfterClass
- public static void clearSettingsProvider() {
- FakeSettingsProvider.clearSettingsProvider();
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
- when(mContext.getSystemServiceName(eq(JobScheduler.class))).thenReturn(
- Context.JOB_SCHEDULER_SERVICE);
- when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler);
- when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
- mContentResolver = new MockContentResolver(mContext);
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- mContactsProvider = new MockContactsProvider(mContext);
- mContentResolver.addProvider(CallLog.AUTHORITY, mContactsProvider);
- when(mContext.getContentResolver()).thenReturn(mContentResolver);
- mPreloadAppsInstaller = new MockPreloadAppsInstaller(mContext);
- mConfiguration = new Configuration();
- mTestPreloadsDir = new File(InstrumentationRegistry.getContext().getFilesDir(),
- TEST_PRELOADS_DIR_NAME);
-
- Settings.Global.putString(mContentResolver, Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
- Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1);
- Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 1);
-
- // Initialize RetailDemoModeService
- mInjector = new TestInjector();
- mService = new RetailDemoModeService(mInjector);
- mService.onStart();
- }
-
- @After
- public void tearDown() {
- if (mTestPreloadsDir != null) {
- FileUtils.deleteContentsAndDir(mTestPreloadsDir);
- }
- }
-
- @Test
- public void testDemoUserSetup() throws Exception {
- mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
-
- mLatch = new CountDownLatch(1);
- final UserInfo userInfo = new UserInfo();
- userInfo.id = TEST_DEMO_USER;
- when(mUm.createUser(anyString(), anyInt())).thenReturn(userInfo);
-
- setCameraPackage(TEST_CAMERA_PKG);
- mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
- assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
- "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
- final ArgumentCaptor<IntentFilter> intentFilter =
- ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
- assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
- intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
-
- // Wait for the setup to complete.
- mLatch.await(SETUP_COMPLETE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- ArgumentCaptor<Integer> flags = ArgumentCaptor.forClass(Integer.class);
- verify(mUm).createUser(anyString(), flags.capture());
- assertTrue("FLAG_DEMO not set during user creation",
- (flags.getValue() & UserInfo.FLAG_DEMO) != 0);
- assertTrue("FLAG_EPHEMERAL not set during user creation",
- (flags.getValue() & UserInfo.FLAG_EPHEMERAL) != 0);
- // Verify if necessary restrictions are being set.
- final UserHandle user = UserHandle.of(TEST_DEMO_USER);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
- // Verify if necessary settings are updated.
- assertEquals("SKIP_FIRST_USE_HINTS setting is not set for demo user",
- Settings.Secure.getIntForUser(mContentResolver,
- Settings.Secure.SKIP_FIRST_USE_HINTS, TEST_DEMO_USER),
- 1);
- assertEquals("PACKAGE_VERIFIER_ENABLE settings should be set to 0 for demo user",
- Settings.Global.getInt(mContentResolver,
- Settings.Global.PACKAGE_VERIFIER_ENABLE),
- 0);
- // Verify if camera is granted location permission.
- verify(mPm).grantRuntimePermission(TEST_CAMERA_PKG,
- Manifest.permission.ACCESS_FINE_LOCATION, user);
- // Verify call logs are cleared.
- assertTrue("Call logs should be deleted", mContactsProvider.isCallLogDeleted());
- }
-
- @Test
- public void testSettingsObserver_disableDemoMode() throws Exception {
- final RetailDemoModeService.SettingsObserver observer =
- mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
- final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
- when(mUm.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM))
- .thenReturn(false);
- Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
- // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
- observer.onChange(false, deviceDemoModeUri);
- final ArgumentCaptor<BroadcastReceiver> receiver =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
-
- Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
- new File(mTestPreloadsDir, "dir1").mkdirs();
- new File(mTestPreloadsDir, "file1").createNewFile();
- Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 0);
- observer.onChange(false, deviceDemoModeUri);
- verify(mContext).unregisterReceiver(receiver.getValue());
- verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, false, UserHandle.SYSTEM);
- assertEquals("Package verifier enable value has not been reset", 1,
- Settings.Global.getInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE));
- Thread.sleep(20); // Wait for the deletion to complete.
- // verify that the preloaded directory is emptied.
- assertEquals("Preloads directory is not emptied",
- 0, mTestPreloadsDir.list().length);
- // Verify that the expiration job was scheduled
- verify(mJobScheduler).schedule(any(JobInfo.class));
- }
-
- @Test
- public void testSettingsObserver_enableDemoMode() throws Exception {
- final RetailDemoModeService.SettingsObserver observer =
- mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
- final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
- // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
- observer.onChange(false, deviceDemoModeUri);
- assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
- "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
- final ArgumentCaptor<IntentFilter> intentFilter =
- ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
- assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
- intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
- }
-
- @Test
- public void testSwitchToDemoUser() {
- // To make the RetailDemoModeService update it's internal state.
- mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
- final RetailDemoModeService.SettingsObserver observer =
- mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
- observer.onChange(false, Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE));
-
- final UserInfo userInfo = new UserInfo(TEST_DEMO_USER, "demo_user",
- UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
- when(mUm.getUserInfo(TEST_DEMO_USER)).thenReturn(userInfo);
- when(mWifiManager.isWifiEnabled()).thenReturn(false);
- final int minVolume = -111;
- for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
- when(mAudioManager.getStreamMinVolume(stream)).thenReturn(minVolume);
- }
-
- mService.onSwitchUser(TEST_DEMO_USER);
- verify(mAmi).updatePersistentConfigurationForUser(mConfiguration, TEST_DEMO_USER);
- for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
- verify(mAudioManager).setStreamVolume(stream, minVolume, 0);
- }
- verify(mLockPatternUtils).setLockScreenDisabled(true, TEST_DEMO_USER);
- verify(mWifiManager).setWifiEnabled(true);
- }
-
- private void setCameraPackage(String pkgName) {
- final ResolveInfo ri = new ResolveInfo();
- final ActivityInfo ai = new ActivityInfo();
- ai.packageName = pkgName;
- ri.activityInfo = ai;
- when(mPm.resolveActivityAsUser(
- argThat(new IntentMatcher(MediaStore.ACTION_IMAGE_CAPTURE)),
- anyInt(),
- eq(TEST_DEMO_USER))).thenReturn(ri);
- }
-
- private class IntentMatcher extends ArgumentMatcher<Intent> {
- private final Intent mIntent;
-
- IntentMatcher(String action) {
- mIntent = new Intent(action);
- }
-
- @Override
- public boolean matchesObject(Object argument) {
- if (argument instanceof Intent) {
- return ((Intent) argument).filterEquals(mIntent);
- }
- return false;
- }
-
- @Override
- public String toString() {
- return "Expected: " + mIntent;
- }
- }
-
- private class MockContactsProvider extends MockContentProvider {
- private boolean mCallLogDeleted;
-
- MockContactsProvider(Context context) {
- super(context);
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- if (CallLog.Calls.CONTENT_URI.equals(uri)) {
- mCallLogDeleted = true;
- }
- return 0;
- }
-
- public boolean isCallLogDeleted() {
- return mCallLogDeleted;
- }
- }
-
- private class MockPreloadAppsInstaller extends PreloadAppsInstaller {
- MockPreloadAppsInstaller(Context context) {
- super(context);
- }
-
- @Override
- public void installApps(int userId) {
- }
- }
-
- private class TestInjector extends Injector {
- private ArrayMap<String, String> mSystemProperties = new ArrayMap<>();
-
- TestInjector() {
- super(mContext);
- }
-
- @Override
- Context getContext() {
- return mContext;
- }
-
- @Override
- UserManager getUserManager() {
- return mUm;
- }
-
- @Override
- WifiManager getWifiManager() {
- return mWifiManager;
- }
-
- @Override
- void switchUser(int userId) {
- if (mLatch != null) {
- mLatch.countDown();
- }
- }
-
- @Override
- AudioManager getAudioManager() {
- return mAudioManager;
- }
-
- @Override
- NotificationManager getNotificationManager() {
- return mNm;
- }
-
- @Override
- ActivityManagerInternal getActivityManagerInternal() {
- return mAmi;
- }
-
- @Override
- PackageManager getPackageManager() {
- return mPm;
- }
-
- @Override
- IPackageManager getIPackageManager() {
- return mIpm;
- }
-
- @Override
- ContentResolver getContentResolver() {
- return mContentResolver;
- }
-
- @Override
- PreloadAppsInstaller getPreloadAppsInstaller() {
- return mPreloadAppsInstaller;
- }
-
- @Override
- void systemPropertiesSet(String key, String value) {
- mSystemProperties.put(key, value);
- }
-
- @Override
- void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
- }
-
- @Override
- void initializeWakeLock() {
- }
-
- @Override
- void destroyWakeLock() {
- }
-
- @Override
- boolean isWakeLockHeld() {
- return false;
- }
-
- @Override
- void acquireWakeLock() {
- }
-
- @Override
- void releaseWakeLock() {
- }
-
- @Override
- void logSessionDuration(int duration) {
- }
-
- @Override
- void logSessionCount(int count) {
- }
-
- @Override
- Configuration getSystemUsersConfiguration() {
- return mConfiguration;
- }
-
- @Override
- LockPatternUtils getLockPatternUtils() {
- return mLockPatternUtils;
- }
-
- @Override
- Notification createResetNotification() {
- return null;
- }
-
- @Override
- File getDataPreloadsDirectory() {
- return mTestPreloadsDir;
- }
-
- @Override
- File getDataPreloadsFileCacheDirectory() {
- return new File(mTestPreloadsDir, "file_cache");
- }
-
- @Override
- void publishLocalService(RetailDemoModeService service,
- RetailDemoModeServiceInternal localService) {
- }
-
- String systemPropertiesGet(String key) {
- return mSystemProperties.get(key);
- }
- }
-}