Merge "Adding an idle timeout to restart demo session" into nyc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
67f82d16ea
@@ -17,22 +17,29 @@
|
||||
package com.android.server.am;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
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.ServiceManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
@@ -43,8 +50,6 @@ 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.pm.UserManagerService;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class RetailDemoModeService extends SystemService {
|
||||
@@ -54,42 +59,89 @@ public class RetailDemoModeService extends SystemService {
|
||||
private static final String DEMO_USER_NAME = "Demo";
|
||||
private static final String ACTION_RESET_DEMO = "com.android.server.am.ACTION_RESET_DEMO";
|
||||
|
||||
private static final long SCREEN_WAKEUP_DELAY = 5000;
|
||||
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 = 30000;
|
||||
|
||||
boolean mDeviceInDemoMode = false;
|
||||
private ActivityManagerService mAms;
|
||||
private NotificationManager mNm;
|
||||
private UserManager mUm;
|
||||
private PowerManager mPm;
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
private Handler mHandler;
|
||||
Handler mHandler;
|
||||
private ServiceThread mHandlerThread;
|
||||
private PendingIntent mResetDemoPendingIntent;
|
||||
|
||||
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!UserManager.isDeviceInDemoMode(getContext())) {
|
||||
if (!mDeviceInDemoMode) {
|
||||
return;
|
||||
}
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_SCREEN_OFF:
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mWakeLock.isHeld()) {
|
||||
mWakeLock.release();
|
||||
}
|
||||
mWakeLock.acquire();
|
||||
}
|
||||
}, SCREEN_WAKEUP_DELAY);
|
||||
mHandler.removeMessages(MSG_TURN_SCREEN_ON);
|
||||
mHandler.sendEmptyMessageDelayed(MSG_TURN_SCREEN_ON, SCREEN_WAKEUP_DELAY);
|
||||
break;
|
||||
case ACTION_RESET_DEMO:
|
||||
createAndSwitchToDemoUser();
|
||||
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) {
|
||||
switch (msg.what) {
|
||||
case MSG_TURN_SCREEN_ON:
|
||||
if (mWakeLock.isHeld()) {
|
||||
mWakeLock.release();
|
||||
}
|
||||
mWakeLock.acquire();
|
||||
break;
|
||||
case MSG_INACTIVITY_TIME_OUT:
|
||||
IPackageManager pm = AppGlobals.getPackageManager();
|
||||
int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
|
||||
String demoLauncherComponent = getContext().getResources()
|
||||
.getString(R.string.config_demoModeLauncherComponent);
|
||||
try {
|
||||
enabledState = pm.getComponentEnabledSetting(
|
||||
ComponentName.unflattenFromString(demoLauncherComponent),
|
||||
getActivityManager().getCurrentUser().id);
|
||||
} catch (RemoteException exc) {
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
case MSG_START_NEW_SESSION:
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Switching to a new demo user");
|
||||
}
|
||||
removeMessages(MSG_START_NEW_SESSION);
|
||||
UserInfo demoUser = getUserManager().createUser(DEMO_USER_NAME,
|
||||
UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
|
||||
if (demoUser != null) {
|
||||
setupDemoUser(demoUser);
|
||||
getActivityManager().switchUser(demoUser.id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RetailDemoModeService(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@@ -103,6 +155,7 @@ public class RetailDemoModeService extends SystemService {
|
||||
.setShowWhen(false)
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setContentIntent(getResetDemoPendingIntent())
|
||||
.setColor(getContext().getColor(R.color.system_notification_accent_color))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -114,23 +167,6 @@ public class RetailDemoModeService extends SystemService {
|
||||
return mResetDemoPendingIntent;
|
||||
}
|
||||
|
||||
private void createAndSwitchToDemoUser() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Switching to a new demo user");
|
||||
}
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UserInfo demoUser = getUserManager().createUser(DEMO_USER_NAME,
|
||||
UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
|
||||
if (demoUser != null) {
|
||||
setupDemoUser(demoUser);
|
||||
getActivityManager().switchUser(demoUser.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void setupDemoUser(UserInfo userInfo) {
|
||||
UserManager um = getUserManager();
|
||||
UserHandle user = UserHandle.of(userInfo.id);
|
||||
@@ -166,14 +202,16 @@ public class RetailDemoModeService extends SystemService {
|
||||
final ContentObserver deviceDemoModeSettingObserver = new ContentObserver(mHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri, int userId) {
|
||||
boolean deviceInDemoMode = UserManager.isDeviceInDemoMode(getContext());
|
||||
if (deviceDemoModeUri.equals(uri)) {
|
||||
if (deviceInDemoMode) {
|
||||
createAndSwitchToDemoUser();
|
||||
mDeviceInDemoMode = UserManager.isDeviceInDemoMode(getContext());
|
||||
if (mDeviceInDemoMode) {
|
||||
mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
|
||||
} else if (mWakeLock.isHeld()) {
|
||||
mWakeLock.release();
|
||||
}
|
||||
}
|
||||
// If device is provisioned and left demo mode - run the cleanup in demo folder
|
||||
if (!deviceInDemoMode && isDeviceProvisioned()) {
|
||||
if (!mDeviceInDemoMode && isDeviceProvisioned()) {
|
||||
// Run on the bg thread to not block the fg thread
|
||||
BackgroundThread.getHandler().post(new Runnable() {
|
||||
@Override
|
||||
@@ -218,7 +256,8 @@ public class RetailDemoModeService extends SystemService {
|
||||
mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND,
|
||||
false);
|
||||
mHandlerThread.start();
|
||||
mHandler = new Handler(mHandlerThread.getLooper(), null, true);
|
||||
mHandler = new MainHandler(mHandlerThread.getLooper());
|
||||
publishLocalService(RetailDemoModeServiceInternal.class, mLocalService);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,7 +271,8 @@ public class RetailDemoModeService extends SystemService {
|
||||
mNm = NotificationManager.from(getContext());
|
||||
|
||||
if (UserManager.isDeviceInDemoMode(getContext())) {
|
||||
createAndSwitchToDemoUser();
|
||||
mDeviceInDemoMode = true;
|
||||
mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
|
||||
}
|
||||
registerSettingsChangeObserver();
|
||||
registerBroadcastReceiver();
|
||||
@@ -240,16 +280,15 @@ public class RetailDemoModeService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void onSwitchUser(int userId) {
|
||||
if (!mDeviceInDemoMode) {
|
||||
return;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "onSwitchUser: " + userId);
|
||||
}
|
||||
UserInfo ui = getUserManager().getUserInfo(userId);
|
||||
if (!ui.isDemo()) {
|
||||
if (UserManager.isDeviceInDemoMode(getContext())) {
|
||||
Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
|
||||
} else if (mWakeLock.isHeld()) {
|
||||
mWakeLock.release();
|
||||
}
|
||||
Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
|
||||
return;
|
||||
}
|
||||
if (!mWakeLock.isHeld()) {
|
||||
@@ -257,4 +296,23 @@ public class RetailDemoModeService extends SystemService {
|
||||
}
|
||||
mNm.notifyAsUser(TAG, 1, createResetNotification(), UserHandle.of(userId));
|
||||
}
|
||||
|
||||
public RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
|
||||
private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000;
|
||||
private long mLastUserActivityTime = 0;
|
||||
|
||||
@Override
|
||||
public void onUserActivity() {
|
||||
if (!mDeviceInDemoMode) {
|
||||
return;
|
||||
}
|
||||
long timeOfActivity = SystemClock.uptimeMillis();
|
||||
if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
|
||||
return;
|
||||
}
|
||||
mLastUserActivityTime = timeOfActivity;
|
||||
mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
|
||||
mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, USER_INACTIVITY_TIMEOUT);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface RetailDemoModeServiceInternal {
|
||||
public void onUserActivity();
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.app.IBatteryStats;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.am.RetailDemoModeServiceInternal;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -91,6 +92,7 @@ final class Notifier {
|
||||
private final ActivityManagerInternal mActivityManagerInternal;
|
||||
private final InputManagerInternal mInputManagerInternal;
|
||||
private final InputMethodManagerInternal mInputMethodManagerInternal;
|
||||
private final RetailDemoModeServiceInternal mRetailDemoModeServiceInternal;
|
||||
|
||||
private final NotifierHandler mHandler;
|
||||
private final Intent mScreenOnIntent;
|
||||
@@ -136,6 +138,7 @@ final class Notifier {
|
||||
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
|
||||
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
|
||||
mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
|
||||
mRetailDemoModeServiceInternal = LocalServices.getService(RetailDemoModeServiceInternal.class);
|
||||
|
||||
mHandler = new NotifierHandler(looper);
|
||||
mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
|
||||
@@ -534,7 +537,9 @@ final class Notifier {
|
||||
}
|
||||
mUserActivityPending = false;
|
||||
}
|
||||
|
||||
if (mRetailDemoModeServiceInternal != null) {
|
||||
mRetailDemoModeServiceInternal.onUserActivity();
|
||||
}
|
||||
mPolicy.userActivity();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user