Merge "Adding a warning dialog before restarting demo session" into nyc-mr1-dev
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c036c36..ae2a9e4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4372,15 +4372,21 @@
<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">Restart Session</string>
+ <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 start a new demo session</string>
+ <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</string>
+ <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">Restarting session</string>
-
-
+ <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\'ll 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>
<!-- Title of notification shown when device has been forced to safe mode after a security compromise. -->
<string name="audit_safemode_notification">Factory reset to use this device without restrictions</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 385c61a..6b7d32d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1892,6 +1892,10 @@
<java-symbol type="string" name="audit_safemode_notification_details" />
<java-symbol type="string" name="reset_retail_demo_mode_title" />
<java-symbol type="string" name="reset_retail_demo_mode_text" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_title" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_countdown" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_left_button" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_right_button" />
<java-symbol type="layout" name="resolver_list" />
<java-symbol type="id" name="resolver_list" />
diff --git a/services/core/java/com/android/server/am/RetailDemoModeService.java b/services/core/java/com/android/server/am/RetailDemoModeService.java
index 6a5ec96..bcf1bd4 100644
--- a/services/core/java/com/android/server/am/RetailDemoModeService.java
+++ b/services/core/java/com/android/server/am/RetailDemoModeService.java
@@ -25,6 +25,7 @@
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;
@@ -44,12 +45,13 @@
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
-
import com.android.internal.os.BackgroundThread;
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.am.UserInactivityCountdownDialog.OnCountDownExpiredListener;
+
import java.io.File;
public class RetailDemoModeService extends SystemService {
@@ -65,6 +67,8 @@
private static final long SCREEN_WAKEUP_DELAY = 2500;
private static final long USER_INACTIVITY_TIMEOUT = 30000;
+ private static final long WARNING_DIALOG_TIMEOUT = 6000;
+ private static final long MILLIS_PER_SECOND = 1000;
boolean mDeviceInDemoMode = false;
private ActivityManagerService mAms;
@@ -110,7 +114,7 @@
mWakeLock.acquire();
break;
case MSG_INACTIVITY_TIME_OUT:
- IPackageManager pm = AppGlobals.getPackageManager();
+ final IPackageManager pm = AppGlobals.getPackageManager();
int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
String demoLauncherComponent = getContext().getResources()
.getString(R.string.config_demoModeLauncherComponent);
@@ -122,8 +126,8 @@
// XXX: shouldn't happen
}
if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
- Slog.i(TAG, "Restarting session due to user inactivity timeout");
- sendEmptyMessage(MSG_START_NEW_SESSION);
+ Slog.i(TAG, "User inactivity timeout reached");
+ showInactivityCountdownDialog();
}
break;
case MSG_START_NEW_SESSION:
@@ -131,7 +135,8 @@
Slog.d(TAG, "Switching to a new demo user");
}
removeMessages(MSG_START_NEW_SESSION);
- UserInfo demoUser = getUserManager().createUser(DEMO_USER_NAME,
+ removeMessages(MSG_INACTIVITY_TIME_OUT);
+ final UserInfo demoUser = getUserManager().createUser(DEMO_USER_NAME,
UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
if (demoUser != null) {
setupDemoUser(demoUser);
@@ -142,6 +147,25 @@
}
}
+ private void showInactivityCountdownDialog() {
+ UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
+ WARNING_DIALOG_TIMEOUT, MILLIS_PER_SECOND);
+ dialog.setPositiveButtonClickListener(null);
+ dialog.setNegativeButtonClickListener(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) {
super(context);
}
@@ -167,7 +191,7 @@
return mResetDemoPendingIntent;
}
- void setupDemoUser(UserInfo userInfo) {
+ private void setupDemoUser(UserInfo userInfo) {
UserManager um = getUserManager();
UserHandle user = UserHandle.of(userInfo.id);
LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
@@ -230,13 +254,13 @@
UserHandle.USER_SYSTEM);
}
- boolean isDeviceProvisioned() {
+ private boolean isDeviceProvisioned() {
return Settings.Global.getInt(
getContext().getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
}
private boolean deleteDemoFolderContents() {
- File dir = Environment.getDataPreloadsDemoDirectory();
+ final File dir = Environment.getDataPreloadsDemoDirectory();
Slog.i(TAG, "Deleting contents of " + dir);
return FileUtils.deleteContents(dir);
}
@@ -286,7 +310,7 @@
if (DEBUG) {
Slog.d(TAG, "onSwitchUser: " + userId);
}
- UserInfo ui = getUserManager().getUserInfo(userId);
+ final UserInfo ui = getUserManager().getUserInfo(userId);
if (!ui.isDemo()) {
Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
return;
diff --git a/services/core/java/com/android/server/am/UserInactivityCountdownDialog.java b/services/core/java/com/android/server/am/UserInactivityCountdownDialog.java
new file mode 100644
index 0000000..1a1e85c
--- /dev/null
+++ b/services/core/java/com/android/server/am/UserInactivityCountdownDialog.java
@@ -0,0 +1,109 @@
+/*
+ * 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.am;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.CountDownTimer;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+public class UserInactivityCountdownDialog extends AlertDialog {
+
+ private OnCountDownExpiredListener mOnCountDownExpiredListener;
+ private View mDialogView;
+ private CountDownTimer mCountDownTimer;
+ private long mCountDownDuration;
+ private long mRefreshInterval;
+
+ protected UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) {
+ super(context);
+
+ mCountDownDuration = duration;
+ mRefreshInterval = refreshInterval;
+ mDialogView = LayoutInflater.from(context).inflate(R.layout.alert_dialog, null);
+ String msg = context.getString(R.string.demo_user_inactivity_timeout_countdown, duration);
+ getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ 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);
+ setView(mDialogView);
+ setMessage(msg);
+ }
+
+ public void setOnCountDownExpiredListener(
+ OnCountDownExpiredListener onCountDownExpiredListener) {
+ mOnCountDownExpiredListener = onCountDownExpiredListener;
+ }
+
+ public void setPositiveButtonClickListener(OnClickListener onClickListener) {
+ setButton(Dialog.BUTTON_POSITIVE,
+ getContext().getString(R.string.demo_user_inactivity_timeout_left_button),
+ onClickListener);
+ }
+
+ public void setNegativeButtonClickListener(OnClickListener onClickListener) {
+ setButton(Dialog.BUTTON_NEGATIVE,
+ getContext().getString(R.string.demo_user_inactivity_timeout_right_button),
+ onClickListener);
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ mDialogView.post(new Runnable() {
+ @Override
+ public void run() {
+ mCountDownTimer = new CountDownTimer(mCountDownDuration, mRefreshInterval) {
+
+ @Override
+ public void onTick(long millisUntilFinished) {
+ String msg = getContext().getResources().getString(
+ R.string.demo_user_inactivity_timeout_countdown,
+ millisUntilFinished / 1000);
+ ((TextView) mDialogView.findViewById(R.id.message)).setText(msg);
+ }
+
+ @Override
+ public void onFinish() {
+ dismiss();
+ if (mOnCountDownExpiredListener != null)
+ mOnCountDownExpiredListener.onCountDownExpired();
+ }
+ }.start();
+ }
+ });
+ }
+
+ @Override
+ public void dismiss() {
+ super.dismiss();
+ if (mCountDownTimer != null) {
+ mCountDownTimer.cancel();
+ }
+ }
+
+ interface OnCountDownExpiredListener {
+ void onCountDownExpired();
+ }
+}