Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f4ae5e1 authored by Suprabh Shukla's avatar Suprabh Shukla Committed by android-build-merger
Browse files

Merge "Adding an idle timeout to restart demo session" into nyc-mr1-dev

am: 67f82d16

* commit '67f82d16':
  Adding an idle timeout to restart demo session

Change-Id: I11db70fd323fb908aa137dedf1817fa28b577d79
parents 47b2ecdd 67f82d16
Loading
Loading
Loading
Loading
+102 −44
Original line number Diff line number Diff line
@@ -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,41 +59,88 @@ 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() {
                    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 run() {
        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);
                    }
                    }, SCREEN_WAKEUP_DELAY);
                    break;
                case ACTION_RESET_DEMO:
                    createAndSwitchToDemoUser();
                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();
            }
            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);
        }
    };
}
+21 −0
Original line number Diff line number Diff line
/*
 * 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();
}
 No newline at end of file
+6 −1
Original line number Diff line number Diff line
@@ -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();
    }