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

Commit cc30b0e7 authored by Suprabh Shukla's avatar Suprabh Shukla
Browse files

Adding RetailModeService to handle retail mode

The service listens for the global setting DEVICE_DEMO_MODE and switches
device to demo mode when it is changed to 1. Also, acquires the wakelock
to
keep the screen on and puts up a notification to wipe and reset the demo
session when in demo mode.

Bug: 27280140
Change-Id: If1843016889ec2c50818c67432d60f33063e0986
parent b0eab235
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -20908,6 +20908,11 @@ public final class ActivityManagerService extends ActivityManagerNative
                Slog.w(TAG, "No user info for user #" + targetUserId);
                return false;
            }
            if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mContext)) {
                Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId
                        + " when device is in demo mode");
                return false;
            }
            if (!targetUserInfo.supportsSwitchTo()) {
                Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
                return false;
+179 −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;

import android.app.ActivityManagerNative;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.PowerManager;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;

import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.pm.UserManagerService;

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 long SCREEN_WAKEUP_DELAY = 5000;

    private ActivityManagerService mAms;
    private UserManagerService mUms;
    private PowerManager mPm;
    private PowerManager.WakeLock mWakeLock;
    private Handler mHandler;
    private ServiceThread mHandlerThread;

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!UserManager.isDeviceInDemoMode(getContext())) {
                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);
                    break;
            }
        }
    };

    public RetailDemoModeService(Context context) {
        super(context);
    }

    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) {
                    getActivityManager().switchUser(demoUser.id);
                }
            }
        });
    }

    private ActivityManagerService getActivityManager() {
        if (mAms == null) {
            mAms = (ActivityManagerService) ActivityManagerNative.getDefault();
        }
        return mAms;
    }

    private UserManagerService getUserManager() {
        if (mUms == null) {
            mUms = (UserManagerService) UserManagerService.Stub
                    .asInterface(ServiceManager.getService(Context.USER_SERVICE));
        }
        return mUms;
    }

    private void registerSettingsChangeObserver() {
        final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
        final ContentResolver cr = getContext().getContentResolver();
        final ContentObserver deviceDemoModeSettingObserver = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange, Uri uri, int userId) {
                if (deviceDemoModeUri.equals(uri)) {
                    if (UserManager.isDeviceInDemoMode(getContext())) {
                        createAndSwitchToDemoUser();
                    }
                }
            }
        };
        cr.registerContentObserver(deviceDemoModeUri, false, deviceDemoModeSettingObserver,
                UserHandle.USER_SYSTEM);
    }

    private void registerBroadcastReceiver() {
        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
    }

    @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 Handler(mHandlerThread.getLooper(), null, true);
    }

    @Override
    public void onBootPhase(int bootPhase) {
        if (bootPhase != PHASE_THIRD_PARTY_APPS_CAN_START) {
            return;
        }
        mPm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
        mWakeLock = mPm
                .newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
        if (UserManager.isDeviceInDemoMode(getContext())) {
            createAndSwitchToDemoUser();
        }
        registerSettingsChangeObserver();
        registerBroadcastReceiver();
    }

    @Override
    public void onSwitchUser(int userId) {
        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()) {
            mWakeLock.acquire();
        }
    }
}
+1 −27
Original line number Diff line number Diff line
@@ -223,8 +223,7 @@ final class UserController {

    private void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
        final int userId = uss.mHandle.getIdentifier();
        boolean deviceInDemoMode = UserManager.isDeviceInDemoMode(mService.mContext);
        boolean switchToDemoUser = false;

        Slog.d(TAG, "Finishing user boot " + userId);
        synchronized (mService) {
            // Bail if we ended up with a stale user
@@ -261,32 +260,7 @@ final class UserController {
            } else {
                maybeUnlockUser(userId);
            }
            if (deviceInDemoMode && mCurrentUserId == UserHandle.USER_SYSTEM) {
                switchToDemoUser = true;
            }
        }

        if (switchToDemoUser) {
            doSwitchToDemoUser();
        }
    }

    private void doSwitchToDemoUser() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // Remove any demo users first
                for (UserInfo user: mUserManager.getUsers(true)) {
                    if (user.isDemo()) {
                        mUserManager.removeUser(user.id);
                    }
        }
                UserInfo demoUser = mUserManager.createUser("Demo", UserInfo.FLAG_DEMO);
                if (demoUser != null) {
                    mService.switchUser(demoUser.id);
                }
            }
        });
    }

    /**
+2 −1
Original line number Diff line number Diff line
@@ -2074,7 +2074,8 @@ public class UserManagerService extends IUserManager.Stub {
                        return null;
                    }
                }
                if (!UserManager.isSplitSystemUser() && (flags & UserInfo.FLAG_EPHEMERAL) != 0) {
                if (!UserManager.isSplitSystemUser() && (flags & UserInfo.FLAG_EPHEMERAL) != 0
                        && (flags & UserInfo.FLAG_DEMO) == 0) {
                    Log.e(LOG_TAG,
                            "Ephemeral users are supported on split-system-user systems only.");
                    return null;
+8 −0
Original line number Diff line number Diff line
@@ -42,7 +42,9 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IMountService;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Slog;
@@ -55,6 +57,7 @@ import com.android.internal.os.ZygoteInit;
import com.android.internal.widget.ILockSettings;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.RetailDemoModeService;
import com.android.server.audio.AudioService;
import com.android.server.camera.CameraService;
import com.android.server.clipboard.ClipboardService;
@@ -1175,6 +1178,11 @@ public final class SystemServer {
        // MMS service broker
        mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);

        if (Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0 ||
                UserManager.isDeviceInDemoMode(mSystemContext)) {
            mSystemServiceManager.startService(RetailDemoModeService.class);
        }

        // It is now time to start up the app processes...

        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeVibratorServiceReady");