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

Commit 7d2822c1 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Powers off display and locks device for Secure Lock Device" into main

parents 8abcd1ae b60384f6
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);
    }
}