/*
 * Copyright 2017, 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 static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.StatusBarManager.DISABLE2_MASK;
import static android.app.StatusBarManager.DISABLE2_NONE;
import static android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE;
import static android.app.StatusBarManager.DISABLE_HOME;
import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
import static android.os.Process.SYSTEM_UID;
import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;

import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_LOCKED;
import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_PINNED;

import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

import android.app.StatusBarManager;
import android.app.admin.DevicePolicyManager;
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.telecom.TelecomManager;
import android.testing.DexmakerShareClassLoaderRule;
import android.util.Pair;

import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.WindowManagerService;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.verification.VerificationMode;

/**
 * Unit tests for {@link LockTaskController}.
 *
 * Build/Install/Run:
 *  bit FrameworksServicesTests:com.android.server.am.LockTaskControllerTest
 */
@Presubmit
@SmallTest
public class LockTaskControllerTest {
    private static final String TEST_PACKAGE_NAME = "com.test.package";
    private static final String TEST_PACKAGE_NAME_2 = "com.test.package2";
    private static final String TEST_CLASS_NAME = ".TestClass";
    private static final int TEST_USER_ID = 123;
    private static final int TEST_UID = 10467;

    @Rule
    public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
            new DexmakerShareClassLoaderRule();

    @Mock private ActivityStackSupervisor mSupervisor;
    @Mock private IDevicePolicyManager mDevicePolicyManager;
    @Mock private IStatusBarService mStatusBarService;
    @Mock private WindowManagerService mWindowManager;
    @Mock private LockPatternUtils mLockPatternUtils;
    @Mock private StatusBarManagerInternal mStatusBarManagerInternal;
    @Mock private TelecomManager mTelecomManager;
    @Mock private RecentTasks mRecentTasks;

    private LockTaskController mLockTaskController;
    private Context mContext;
    private String mLockToAppSetting;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mContext = InstrumentationRegistry.getTargetContext();
        mLockToAppSetting = Settings.Secure.getString(mContext.getContentResolver(),
                Settings.Secure.LOCK_TO_APP_EXIT_LOCKED);

        if (Looper.myLooper() == null) {
            Looper.prepare();
        }

        mSupervisor.mRecentTasks = mRecentTasks;

        mLockTaskController = new LockTaskController(mContext, mSupervisor,
                new ImmediatelyExecuteHandler());
        mLockTaskController.setWindowManager(mWindowManager);
        mLockTaskController.mStatusBarService = mStatusBarService;
        mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
        mLockTaskController.mTelecomManager = mTelecomManager;
        mLockTaskController.mLockPatternUtils = mLockPatternUtils;

        LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
        LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
    }

    @After
    public void tearDown() throws Exception {
        Settings.Secure.putString(mContext.getContentResolver(),
                Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, mLockToAppSetting);
    }

    @Test
    public void testPreconditions() {
        // GIVEN nothing has happened

        // THEN current lock task mode should be NONE
        assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
    }

    @Test
    public void testStartLockTaskMode_once() throws Exception {
        // GIVEN a task record with whitelisted auth
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);

        // WHEN calling setLockTaskMode for LOCKED mode without resuming
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // THEN the lock task mode state should be LOCKED
        assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
        // THEN the task should be locked
        assertTrue(mLockTaskController.isTaskLocked(tr));

        // THEN lock task mode should be started
        verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
    }

    @Test
    public void testStartLockTaskMode_twice() throws Exception {
        // GIVEN two task records with whitelisted auth
        TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);

        // WHEN calling setLockTaskMode for LOCKED mode on both tasks
        mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
        mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);

        // THEN the lock task mode state should be LOCKED
        assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
        // THEN neither of the tasks should be able to move to back of stack
        assertTrue(mLockTaskController.isTaskLocked(tr1));
        assertTrue(mLockTaskController.isTaskLocked(tr2));

        // THEN lock task mode should be started
        verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
    }

    @Test
    public void testStartLockTaskMode_pinningRequest() throws Exception {
        // GIVEN a task record that is not whitelisted, i.e. with pinned auth
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE);

        // WHEN calling startLockTaskMode
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // THEN a pinning request should be shown
        verify(mStatusBarManagerInternal).showScreenPinningRequest(anyInt());
    }

    @Test
    public void testStartLockTaskMode_pinnedBySystem() throws Exception {
        // GIVEN a task record with pinned auth
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE);

        // WHEN the system calls startLockTaskMode
        mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID);

        // THEN the lock task mode state should be PINNED
        assertEquals(LOCK_TASK_MODE_PINNED, mLockTaskController.getLockTaskModeState());
        // THEN the task should be locked
        assertTrue(mLockTaskController.isTaskLocked(tr));

        // THEN lock task mode should be started
        verifyLockTaskStarted(STATUS_BAR_MASK_PINNED, DISABLE2_NONE);
        // THEN screen pinning toast should be shown
        verify(mStatusBarService).showPinningEnterExitToast(true /* entering */);
    }

    @Test
    public void testLockTaskViolation() throws Exception {
        // GIVEN one task record with whitelisted auth that is in lock task mode
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // THEN it's not a lock task violation to try and launch this task without clearing
        assertFalse(mLockTaskController.isLockTaskModeViolation(tr, false));

        // THEN it's a lock task violation to launch another task that is not whitelisted
        assertTrue(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
                TaskRecord.LOCK_TASK_AUTH_PINNABLE)));
        // THEN it's a lock task violation to launch another task that is disallowed from lock task
        assertTrue(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
                TaskRecord.LOCK_TASK_AUTH_DONT_LOCK)));

        // THEN it's no a lock task violation to launch another task that is whitelisted
        assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
                TaskRecord.LOCK_TASK_AUTH_WHITELISTED)));
        assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
                TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE)));
        // THEN it's not a lock task violation to launch another task that is priv launchable
        assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
                TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV)));
    }

    @Test
    public void testLockTaskViolation_emergencyCall() throws Exception {
        // GIVEN one task record with whitelisted auth that is in lock task mode
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // GIVEN tasks necessary for emergency calling
        TaskRecord keypad = getTaskRecord(new Intent().setComponent(EMERGENCY_DIALER_COMPONENT),
                TaskRecord.LOCK_TASK_AUTH_PINNABLE);
        TaskRecord callAction = getTaskRecord(new Intent(Intent.ACTION_CALL_EMERGENCY),
                TaskRecord.LOCK_TASK_AUTH_PINNABLE);
        TaskRecord dialer = getTaskRecord("com.example.dialer", TaskRecord.LOCK_TASK_AUTH_PINNABLE);
        when(mTelecomManager.getSystemDialerPackage())
                .thenReturn(dialer.intent.getComponent().getPackageName());

        // GIVEN keyguard is allowed for lock task mode
        mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_KEYGUARD);

        // THEN the above tasks should all be allowed
        assertFalse(mLockTaskController.isLockTaskModeViolation(keypad));
        assertFalse(mLockTaskController.isLockTaskModeViolation(callAction));
        assertFalse(mLockTaskController.isLockTaskModeViolation(dialer));

        // GIVEN keyguard is disallowed for lock task mode (default)
        mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_NONE);

        // THEN the above tasks should all be blocked
        assertTrue(mLockTaskController.isLockTaskModeViolation(keypad));
        assertTrue(mLockTaskController.isLockTaskModeViolation(callAction));
        assertTrue(mLockTaskController.isLockTaskModeViolation(dialer));
    }

    @Test
    public void testStopLockTaskMode() throws Exception {
        // GIVEN one task record with whitelisted auth that is in lock task mode
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // WHEN the same caller calls stopLockTaskMode
        mLockTaskController.stopLockTaskMode(tr, false, TEST_UID);

        // THEN the lock task mode should be NONE
        assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
        // THEN the task should no longer be locked
        assertFalse(mLockTaskController.isTaskLocked(tr));
        // THEN lock task mode should have been finished
        verifyLockTaskStopped(times(1));
    }

    @Test(expected = SecurityException.class)
    public void testStopLockTaskMode_differentCaller() throws Exception {
        // GIVEN one task record with whitelisted auth that is in lock task mode
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // WHEN a different caller calls stopLockTaskMode
        mLockTaskController.stopLockTaskMode(tr, false, TEST_UID + 1);

        // THEN security exception should be thrown, because different caller tried to unlock
    }

    @Test
    public void testStopLockTaskMode_systemCaller() throws Exception {
        // GIVEN one task record with whitelisted auth that is in lock task mode
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // WHEN system calls stopLockTaskMode
        mLockTaskController.stopLockTaskMode(tr, true, SYSTEM_UID);

        // THEN lock task mode should still be active
        assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
    }

    @Test
    public void testStopLockTaskMode_twoTasks() throws Exception {
        // GIVEN two task records with whitelisted auth that is in lock task mode
        TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
        mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);

        // WHEN calling stopLockTaskMode
        mLockTaskController.stopLockTaskMode(tr2, false, TEST_UID);

        // THEN the lock task mode should still be active
        assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
        // THEN the first task should still be locked
        assertTrue(mLockTaskController.isTaskLocked(tr1));
        // THEN the top task should no longer be locked
        assertFalse(mLockTaskController.isTaskLocked(tr2));
        // THEN lock task mode should not have been finished
        verifyLockTaskStopped(never());
    }

    @Test
    public void testStopLockTaskMode_rootTask() throws Exception {
        // GIVEN two task records with whitelisted auth that is in lock task mode
        TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
        mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);

        // WHEN calling stopLockTaskMode on the root task
        mLockTaskController.stopLockTaskMode(tr1, false, TEST_UID);

        // THEN the lock task mode should be inactive
        assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
        // THEN the first task should no longer be locked
        assertFalse(mLockTaskController.isTaskLocked(tr1));
        // THEN the top task should no longer be locked
        assertFalse(mLockTaskController.isTaskLocked(tr2));
        // THEN lock task mode should be finished
        verifyLockTaskStopped(times(1));
    }

    @Test
    public void testStopLockTaskMode_pinned() throws Exception {
        // GIVEN one task records that is in pinned mode
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE);
        mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID);
        // GIVEN that the keyguard is required to show after unlocking
        Settings.Secure.putInt(mContext.getContentResolver(),
                Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 1);

        // reset invocation counter
        reset(mStatusBarService);

        // WHEN calling stopLockTask
        mLockTaskController.stopLockTaskMode(null, true, SYSTEM_UID);

        // THEN the lock task mode should no longer be active
        assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
        // THEN the task should no longer be locked
        assertFalse(mLockTaskController.isTaskLocked(tr));
        // THEN lock task mode should have been finished
        verifyLockTaskStopped(times(1));
        // THEN the keyguard should be shown
        verify(mLockPatternUtils).requireCredentialEntry(UserHandle.USER_ALL);
        // THEN screen pinning toast should be shown
        verify(mStatusBarService).showPinningEnterExitToast(false /* entering */);
    }

    @Test
    public void testClearLockedTasks() throws Exception {
        // GIVEN two task records with whitelisted auth that is in lock task mode
        TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
        mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);

        // WHEN calling stopLockTaskMode on the root task
        mLockTaskController.clearLockedTasks("testClearLockedTasks");

        // THEN the lock task mode should be inactive
        assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
        // THEN the first task should no longer be locked
        assertFalse(mLockTaskController.isTaskLocked(tr1));
        // THEN the top task should no longer be locked
        assertFalse(mLockTaskController.isTaskLocked(tr2));
        // THEN lock task mode should be finished
        verifyLockTaskStopped(times(1));
    }

    @Test
    public void testUpdateLockTaskPackages() throws Exception {
        String[] whitelist1 = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
        String[] whitelist2 = {TEST_PACKAGE_NAME};

        // No package is whitelisted initially
        for (String pkg : whitelist1) {
            assertFalse("Package shouldn't be whitelisted: " + pkg,
                    mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg));
            assertFalse("Package shouldn't be whitelisted for user 0: " + pkg,
                    mLockTaskController.isPackageWhitelisted(0, pkg));
        }

        // Apply whitelist
        mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist1);

        // Assert the whitelist is applied to the correct user
        for (String pkg : whitelist1) {
            assertTrue("Package should be whitelisted: " + pkg,
                    mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg));
            assertFalse("Package shouldn't be whitelisted for user 0: " + pkg,
                    mLockTaskController.isPackageWhitelisted(0, pkg));
        }

        // Update whitelist
        mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist2);

        // Assert the new whitelist is applied
        assertTrue("Package should remain whitelisted: " + TEST_PACKAGE_NAME,
                mLockTaskController.isPackageWhitelisted(TEST_USER_ID, TEST_PACKAGE_NAME));
        assertFalse("Package should no longer be whitelisted: " + TEST_PACKAGE_NAME_2,
                mLockTaskController.isPackageWhitelisted(TEST_USER_ID, TEST_PACKAGE_NAME_2));
    }

    @Test
    public void testUpdateLockTaskPackages_taskRemoved() throws Exception {
        // GIVEN two tasks which are whitelisted initially
        TaskRecord tr1 = getTaskRecordForUpdate(TEST_PACKAGE_NAME, true);
        TaskRecord tr2 = getTaskRecordForUpdate(TEST_PACKAGE_NAME_2, false);
        String[] whitelist = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
        mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);

        // GIVEN the tasks are launched into LockTask mode
        mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
        mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
        assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
        assertTrue(mLockTaskController.isTaskLocked(tr1));
        assertTrue(mLockTaskController.isTaskLocked(tr2));
        verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);

        // WHEN removing one package from whitelist
        whitelist = new String[] {TEST_PACKAGE_NAME};
        mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);

        // THEN the task running that package should be stopped
        verify(tr2).performClearTaskLocked();
        assertFalse(mLockTaskController.isTaskLocked(tr2));
        // THEN the other task should remain locked
        assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
        assertTrue(mLockTaskController.isTaskLocked(tr1));
        verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);

        // WHEN removing the last package from whitelist
        whitelist = new String[] {};
        mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);

        // THEN the last task should be cleared, and the system should quit LockTask mode
        verify(tr1).performClearTaskLocked();
        assertFalse(mLockTaskController.isTaskLocked(tr1));
        assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
        verifyLockTaskStopped(times(1));
    }

    @Test
    public void testUpdateLockTaskFeatures() throws Exception {
        // GIVEN a locked task
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // THEN lock task mode should be started with default status bar masks
        verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);

        // reset invocation counter
        reset(mStatusBarService);

        // WHEN home button is enabled for lock task mode
        mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_HOME);

        // THEN status bar should be updated to reflect this change
        int expectedFlags = STATUS_BAR_MASK_LOCKED
                & ~DISABLE_HOME;
        int expectedFlags2 = DISABLE2_MASK;
        verify(mStatusBarService).disable(eq(expectedFlags), any(IBinder.class),
                eq(mContext.getPackageName()));
        verify(mStatusBarService).disable2(eq(expectedFlags2), any(IBinder.class),
                eq(mContext.getPackageName()));

        // reset invocation counter
        reset(mStatusBarService);

        // WHEN notifications are enabled for lock task mode
        mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_NOTIFICATIONS);

        // THEN status bar should be updated to reflect this change
        expectedFlags = STATUS_BAR_MASK_LOCKED
                & ~DISABLE_NOTIFICATION_ICONS
                & ~DISABLE_NOTIFICATION_ALERTS;
        expectedFlags2 = DISABLE2_MASK
                & ~DISABLE2_NOTIFICATION_SHADE;
        verify(mStatusBarService).disable(eq(expectedFlags), any(IBinder.class),
                eq(mContext.getPackageName()));
        verify(mStatusBarService).disable2(eq(expectedFlags2), any(IBinder.class),
                eq(mContext.getPackageName()));
    }

    @Test
    public void testUpdateLockTaskFeatures_differentUser() throws Exception {
        // GIVEN a locked task
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // THEN lock task mode should be started with default status bar masks
        verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);

        // reset invocation counter
        reset(mStatusBarService);

        // WHEN home button is enabled for lock task mode for another user
        mLockTaskController.updateLockTaskFeatures(TEST_USER_ID + 1, LOCK_TASK_FEATURE_HOME);

        // THEN status bar shouldn't change
        verify(mStatusBarService, never()).disable(anyInt(), any(IBinder.class),
                eq(mContext.getPackageName()));
        verify(mStatusBarService, never()).disable2(anyInt(), any(IBinder.class),
                eq(mContext.getPackageName()));
    }

    @Test
    public void testUpdateLockTaskFeatures_keyguard() throws Exception {
        // GIVEN a locked task
        TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);

        // THEN keyguard should be disabled
        verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString());

        // WHEN keyguard is enabled for lock task mode
        mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_KEYGUARD);

        // THEN keyguard should be enabled
        verify(mWindowManager).reenableKeyguard(any(IBinder.class));

        // WHEN keyguard is disabled again for lock task mode
        mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_NONE);

        // THEN keyguard should be disabled
        verify(mWindowManager, times(2)).disableKeyguard(any(IBinder.class), anyString());
    }

    @Test
    public void testGetStatusBarDisableFlags() {
        // Note that we don't enumerate all StatusBarManager flags, but only choose a subset to test

        // WHEN nothing is enabled
        Pair<Integer, Integer> flags = mLockTaskController.getStatusBarDisableFlags(
                LOCK_TASK_FEATURE_NONE);
        // THEN unsupported feature flags should still be untouched
        assertTrue((~STATUS_BAR_MASK_LOCKED & flags.first) == 0);
        // THEN everything else should be disabled
        assertTrue((StatusBarManager.DISABLE_CLOCK & flags.first) != 0);
        assertTrue((StatusBarManager.DISABLE2_QUICK_SETTINGS & flags.second) != 0);

        // WHEN only home button is enabled
        flags = mLockTaskController.getStatusBarDisableFlags(
                LOCK_TASK_FEATURE_HOME);
        // THEN unsupported feature flags should still be untouched
        assertTrue((~STATUS_BAR_MASK_LOCKED & flags.first) == 0);
        // THEN home button should indeed be enabled
        assertTrue((StatusBarManager.DISABLE_HOME & flags.first) == 0);
        // THEN other feature flags should remain disabled
        assertTrue((StatusBarManager.DISABLE2_NOTIFICATION_SHADE & flags.second) != 0);

        // WHEN only global actions menu and notifications are enabled
        flags = mLockTaskController.getStatusBarDisableFlags(
                DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
                        | DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS);
        // THEN unsupported feature flags should still be untouched
        assertTrue((~STATUS_BAR_MASK_LOCKED & flags.first) == 0);
        // THEN notifications should be enabled
        assertTrue((StatusBarManager.DISABLE_NOTIFICATION_ICONS & flags.first) == 0);
        assertTrue((StatusBarManager.DISABLE_NOTIFICATION_ALERTS & flags.first) == 0);
        assertTrue((StatusBarManager.DISABLE2_NOTIFICATION_SHADE & flags.second) == 0);
        // THEN global actions should be enabled
        assertTrue((StatusBarManager.DISABLE2_GLOBAL_ACTIONS & flags.second) == 0);
        // THEN quick settings should still be disabled
        assertTrue((StatusBarManager.DISABLE2_QUICK_SETTINGS & flags.second) != 0);
    }

    private TaskRecord getTaskRecord(int lockTaskAuth) {
        return getTaskRecord(TEST_PACKAGE_NAME, lockTaskAuth);
    }

    private TaskRecord getTaskRecord(String pkg, int lockTaskAuth) {
        final Intent intent = new Intent()
                .setComponent(ComponentName.createRelative(pkg, TEST_CLASS_NAME));
        return getTaskRecord(intent, lockTaskAuth);
    }

    private TaskRecord getTaskRecord(Intent intent, int lockTaskAuth) {
        TaskRecord tr = mock(TaskRecord.class);
        tr.mLockTaskAuth = lockTaskAuth;
        tr.intent = intent;
        tr.userId = TEST_USER_ID;
        return tr;
    }

    /**
     * @param isAppAware {@code true} if the app has marked if_whitelisted in its manifest
     */
    private TaskRecord getTaskRecordForUpdate(String pkg, boolean isAppAware) {
        final int authIfWhitelisted = isAppAware
                ? TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE
                : TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
        TaskRecord tr = getTaskRecord(pkg, authIfWhitelisted);
        doAnswer((invocation) -> {
            boolean isWhitelisted =
                    mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg);
            tr.mLockTaskAuth = isWhitelisted
                    ? authIfWhitelisted
                    : TaskRecord.LOCK_TASK_AUTH_PINNABLE;
            return null;
        }).when(tr).setLockTaskAuth();
        return tr;
    }

    private void verifyLockTaskStarted(int statusBarMask, int statusBarMask2) throws Exception {
        // THEN the keyguard should have been disabled
        verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString());
        // THEN the status bar should have been disabled
        verify(mStatusBarService).disable(eq(statusBarMask), any(IBinder.class),
                eq(mContext.getPackageName()));
        verify(mStatusBarService).disable2(eq(statusBarMask2), any(IBinder.class),
                eq(mContext.getPackageName()));
        // THEN recents should have been notified
        verify(mRecentTasks).onLockTaskModeStateChanged(anyInt(), eq(TEST_USER_ID));
        // THEN the DO/PO should be informed about the operation
        verify(mDevicePolicyManager).notifyLockTaskModeChanged(true, TEST_PACKAGE_NAME,
                TEST_USER_ID);
    }

    private void verifyLockTaskStopped(VerificationMode mode) throws Exception {
        // THEN the keyguard should have been disabled
        verify(mWindowManager, mode).reenableKeyguard(any(IBinder.class));
        // THEN the status bar should have been disabled
        verify(mStatusBarService, mode).disable(eq(StatusBarManager.DISABLE_NONE),
                any(IBinder.class), eq(mContext.getPackageName()));
        verify(mStatusBarService, mode).disable2(eq(StatusBarManager.DISABLE2_NONE),
                any(IBinder.class), eq(mContext.getPackageName()));
        // THEN the DO/PO should be informed about the operation
        verify(mDevicePolicyManager, mode).notifyLockTaskModeChanged(false, null, TEST_USER_ID);
    }

    /**
     * Special handler implementation that executes any message / runnable posted immediately on the
     * thread that it's posted on rather than enqueuing them on its looper.
     */
    private static class ImmediatelyExecuteHandler extends Handler {
        @Override
        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            if (msg.getCallback() != null) {
                msg.getCallback().run();
            }
            return true;
        }
    }
}
