diff options
17 files changed, 12 insertions, 1869 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f5597b8eac8e..53c82e6c5237 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10132,22 +10132,6 @@ public final class Settings { 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 e212c432558c..fa645f4d4c6a 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -315,7 +315,6 @@ message GlobalSettingsProto { 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 8c26db43fc41..65c52792226b 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4538,22 +4538,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 949fd166c14c..e292c9dfbe67 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -304,7 +304,6 @@ public class SettingsBackupTest { 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 b328933cd1c5..819ee3ee57ff 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 @@ class SettingsProtoDumpUtil { 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 6a73d5f65351..0986e0a4aad4 100644 --- a/services/Android.mk +++ b/services/Android.mk @@ -34,7 +34,6 @@ services := \ net \ print \ restrictions \ - retaildemo \ usage \ usb \ voiceinteraction diff --git a/services/art-profile b/services/art-profile index bd6ed23fa993..140465a1c35e 100644 --- a/services/art-profile +++ b/services/art-profile @@ -11901,23 +11901,6 @@ PLcom/android/server/restrictions/RestrictionsManagerService$RestrictionsManager PLcom/android/server/restrictions/RestrictionsManagerService;->-wrap0(Lcom/android/server/restrictions/RestrictionsManagerService;Ljava/lang/String;)Landroid/os/IBinder; PLcom/android/server/restrictions/RestrictionsManagerService;-><init>(Landroid/content/Context;)V PLcom/android/server/restrictions/RestrictionsManagerService;->onStart()V -PLcom/android/server/retaildemo/RetailDemoModeService$1;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService;)V -PLcom/android/server/retaildemo/RetailDemoModeService$1;->onUserActivity()V -PLcom/android/server/retaildemo/RetailDemoModeService$Injector;-><init>(Landroid/content/Context;)V -PLcom/android/server/retaildemo/RetailDemoModeService$Injector;->getContentResolver()Landroid/content/ContentResolver; -PLcom/android/server/retaildemo/RetailDemoModeService$Injector;->getContext()Landroid/content/Context; -PLcom/android/server/retaildemo/RetailDemoModeService$Injector;->publishLocalService(Lcom/android/server/retaildemo/RetailDemoModeService;Landroid/app/RetailDemoModeServiceInternal;)V -PLcom/android/server/retaildemo/RetailDemoModeService$MainHandler;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService;Landroid/os/Looper;)V -PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;->-wrap0(Lcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;)V -PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService;Landroid/os/Handler;)V -PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;->refreshTimeoutConstants()V -PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;->register()V -PLcom/android/server/retaildemo/RetailDemoModeService;->-get1(Lcom/android/server/retaildemo/RetailDemoModeService;)Lcom/android/server/retaildemo/RetailDemoModeService$Injector; -PLcom/android/server/retaildemo/RetailDemoModeService;->-wrap2(Lcom/android/server/retaildemo/RetailDemoModeService;Ljava/lang/Class;Ljava/lang/Object;)V -PLcom/android/server/retaildemo/RetailDemoModeService;-><init>(Landroid/content/Context;)V -PLcom/android/server/retaildemo/RetailDemoModeService;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService$Injector;)V -PLcom/android/server/retaildemo/RetailDemoModeService;->onBootPhase(I)V -PLcom/android/server/retaildemo/RetailDemoModeService;->onStart()V PLcom/android/server/search/SearchManagerService$GlobalSearchProviderObserver;-><init>(Lcom/android/server/search/SearchManagerService;Landroid/content/ContentResolver;)V PLcom/android/server/search/SearchManagerService$Lifecycle$1;-><init>(Lcom/android/server/search/SearchManagerService$Lifecycle;I)V PLcom/android/server/search/SearchManagerService$Lifecycle$1;->run()V diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index c68854286a19..0c72326095a6 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.SystemClock; 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 @@ public final class PowerManagerService extends SystemService // 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 @@ public final class PowerManagerService extends SystemService 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 @@ public final class PowerManagerService extends SystemService } } + 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 85747287cf93..3757b7d0c53d 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -99,7 +99,6 @@ import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; import com.android.server.broadcastradio.BroadcastRadioService; 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; @@ -1536,10 +1535,6 @@ public final class SystemServer { 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/retaildemo/Android.mk b/services/retaildemo/Android.mk deleted file mode 100644 index 670c6bfa1e6a..000000000000 --- 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 90c58d0279a7..000000000000 --- 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 711d4d9d8a91..000000000000 --- 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 013eab8679a8..000000000000 --- 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 0ffe6e4db6b8..597a5849a1a0 100644 --- a/services/tests/notification/Android.mk +++ b/services/tests/notification/Android.mk @@ -18,7 +18,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ 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 0ff11c1f58f8..507b4830e455 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -19,7 +19,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ 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 cf27a503efd4..000000000000 --- 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 a93f64396d57..000000000000 --- 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); - } - } -} |