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

Commit b60384f6 authored by Grace Cheng's avatar Grace Cheng
Browse files

Powers off display and locks device for Secure Lock Device

When secure lock device is enabled, powers off the display and locks the
device

Bug: 401645997
Bug: 398058587
Flag: android.security.secure_lockdown
Test: atest FrameworksServicesTests:SecureLockDeviceServiceTest
Change-Id: Idcbd1355985c4164ad1427f80ce0b87b63fbf3bf
parent 8392a9a2
Loading
Loading
Loading
Loading
+33 −4
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.security.authenticationpolicy;

import android.annotation.NonNull;
import android.content.Context;
import android.os.PowerManager;
import android.os.SystemClock;
import android.security.authenticationpolicy.AuthenticationPolicyManager;
import android.security.authenticationpolicy.AuthenticationPolicyManager.DisableSecureLockDeviceRequestStatus;
import android.security.authenticationpolicy.AuthenticationPolicyManager.EnableSecureLockDeviceRequestStatus;
@@ -25,8 +27,10 @@ import android.security.authenticationpolicy.DisableSecureLockDeviceParams;
import android.security.authenticationpolicy.EnableSecureLockDeviceParams;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.wm.WindowManagerInternal;

/**
 * System service for remotely calling secure lock on the device.
@@ -43,8 +47,14 @@ public class SecureLockDeviceService extends SecureLockDeviceServiceInternal {
    private static final String TAG = "SecureLockDeviceService";
    private final Context mContext;

    public SecureLockDeviceService(@NonNull Context context) {
    private final PowerManager mPowerManager;

    // Not final because initialized after SecureLockDeviceService in SystemServer
    private WindowManagerInternal mWindowManagerInternal;

    SecureLockDeviceService(@NonNull Context context) {
        mContext = context;
        mPowerManager = context.getSystemService(PowerManager.class);
    }

    private void start() {
@@ -52,6 +62,11 @@ public class SecureLockDeviceService extends SecureLockDeviceServiceInternal {
        LocalServices.addService(SecureLockDeviceServiceInternal.class, this);
    }

    @VisibleForTesting
    void onLockSettingsReady() {
        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
    }

    /**
     * @see AuthenticationPolicyManager#enableSecureLockDevice
     * @param params EnableSecureLockDeviceParams for caller to supply params related
@@ -64,9 +79,15 @@ public class SecureLockDeviceService extends SecureLockDeviceServiceInternal {
    @Override
    @EnableSecureLockDeviceRequestStatus
    public int enableSecureLockDevice(EnableSecureLockDeviceParams params) {
        // (1) Call into system_server to lock device, configure allowed auth types
        // for secure lock
        // TODO: lock device, configure allowed authentication types for device entry
        // TODO: Call into system_server to configure allowed auth types for device entry

        // Power off the display
        mPowerManager.goToSleep(SystemClock.uptimeMillis(),
                PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);

        // Lock the device
        mWindowManagerInternal.lockNow();

        // (2) Call into framework to configure secure lock 2FA lockscreen
        // update, UI & string updates
        // TODO: implement 2FA lockscreen when SceneContainerFlag.isEnabled()
@@ -116,5 +137,13 @@ public class SecureLockDeviceService extends SecureLockDeviceServiceInternal {
            mService.start();
            Slog.i(TAG, "Started SecureLockDeviceService");
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == PHASE_LOCK_SETTINGS_READY) {
                Slog.i(TAG, "onBootPhase(PHASE_LOCK_SETTINGS_READY)");
                mService.onLockSettingsReady();
            }
        }
    }
}
+105 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.security.authenticationpolicy;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.verify;

import android.annotation.SuppressLint;
import android.os.IPowerManager;
import android.os.IThermalService;
import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.security.authenticationpolicy.DisableSecureLockDeviceParams;
import android.security.authenticationpolicy.EnableSecureLockDeviceParams;
import android.testing.TestableContext;

import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.util.test.LocalServiceKeeperRule;
import com.android.server.wm.WindowManagerInternal;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

/**
 * atest FrameworksServicesTests:SecureLockDeviceServiceTest
 */
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SecureLockDeviceServiceTest {
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    @Rule public final TestableContext mContext = new TestableContext(
            InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
    @Rule public LocalServiceKeeperRule mLocalServiceKeeperRule = new LocalServiceKeeperRule();
    @Rule public MockitoRule mockito = MockitoJUnit.rule();

    @Mock private IPowerManager mIPowerManager;
    @Mock private IThermalService mThermalService;
    @Mock private SecureLockDeviceServiceInternal mSecureLockDeviceServiceInternal;
    @Mock private WindowManagerInternal mWindowManagerInternal;

    private final EnableSecureLockDeviceParams mEnableParams =
            new EnableSecureLockDeviceParams("test");
    private final DisableSecureLockDeviceParams mDisableParams =
            new DisableSecureLockDeviceParams("test");

    private SecureLockDeviceService mSecureLockDeviceService;

    @SuppressLint("VisibleForTests")
    @Before
    public void setUp() {
        // Unable to mock PowerManager directly because final class
        mContext.addMockSystemService(PowerManager.class,
                new PowerManager(mContext, mIPowerManager, mThermalService, null));

        mLocalServiceKeeperRule.overrideLocalService(SecureLockDeviceServiceInternal.class,
                mSecureLockDeviceServiceInternal);
        mLocalServiceKeeperRule.overrideLocalService(WindowManagerInternal.class,
                mWindowManagerInternal);

        mSecureLockDeviceService = new SecureLockDeviceService(mContext);
        mSecureLockDeviceService.onLockSettingsReady();
    }

    @Test
    public void enableSecureLockDevice_goesToSleep_locksDevice() throws RemoteException {
        enableSecureLockDevice();

        verify(mIPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
        verify(mWindowManagerInternal).lockNow();
    }

    private int enableSecureLockDevice() {
        return mSecureLockDeviceService.enableSecureLockDevice(mEnableParams);
    }

    private int disableSecureLockDevice() {
        return mSecureLockDeviceService.disableSecureLockDevice(mDisableParams);
    }
}