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

Commit a28a3bba authored by Vladimir Komsiyski's avatar Vladimir Komsiyski
Browse files

Handle lockdown in VDM

Turn off all virtual displays when entering lockdown mode.
Restore the virtual display state when existing lockdown mode.

Fix: 300047537
Test: manual with the VDM demo app
Flag: android.companion.virtualdevice.flags.device_aware_display_power
Change-Id: Ie99c1de6db142d10a952c8adcf981e42f01b20bd
parent 6731d99b
Loading
Loading
Loading
Loading
+59 −24
Original line number Diff line number Diff line
@@ -215,6 +215,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    @GuardedBy("mVirtualDeviceLock")
    @Nullable
    private LocaleList mLocaleList = null;
    @GuardedBy("mVirtualDeviceLock")
    private boolean mLockdownActive = false;
    @GuardedBy("mVirtualDeviceLock")
    private boolean mRequestedToBeAwake = true;

    @NonNull
    private final VirtualDevice mPublicVirtualDeviceObject;
@@ -478,6 +482,20 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        }
    }

    void onLockdownChanged(boolean lockdownActive) {
        synchronized (mVirtualDeviceLock) {
            if (lockdownActive != mLockdownActive) {
                mLockdownActive = lockdownActive;
                if (mLockdownActive) {
                    goToSleepInternal(PowerManager.GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF);
                } else if (mRequestedToBeAwake) {
                    wakeUpInternal(PowerManager.WAKE_REASON_DISPLAY_GROUP_TURNED_ON,
                            "android.server.companion.virtual:LOCKDOWN_ENDED");
                }
            }
        }
    }

    @VisibleForTesting
    SensorController getSensorControllerForTest() {
        return mSensorController;
@@ -582,20 +600,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
    public void goToSleep() {
        super.goToSleep_enforcePermission();
        final long now = SystemClock.uptimeMillis();
        final long ident = Binder.clearCallingIdentity();
        try {
        synchronized (mVirtualDeviceLock) {
                for (int i = 0; i < mVirtualDisplays.size(); i++) {
                    VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
                    if (!wrapper.isTrusted() || wrapper.isMirror()) {
                        continue;
                    }
                    int displayId = mVirtualDisplays.keyAt(i);
                    mPowerManager.goToSleep(displayId, now,
                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, /* flags= */ 0);
                }
            mRequestedToBeAwake = false;
        }
        final long ident = Binder.clearCallingIdentity();
        try {
            goToSleepInternal(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
@@ -605,20 +615,17 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
    public void wakeUp() {
        super.wakeUp_enforcePermission();
        final long now = SystemClock.uptimeMillis();
        final long ident = Binder.clearCallingIdentity();
        try {
        synchronized (mVirtualDeviceLock) {
                for (int i = 0; i < mVirtualDisplays.size(); i++) {
                    VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
                    if (!wrapper.isTrusted() || wrapper.isMirror()) {
                        continue;
                    }
                    int displayId = mVirtualDisplays.keyAt(i);
                    mPowerManager.wakeUp(now, PowerManager.WAKE_REASON_POWER_BUTTON,
                            "android.server.companion.virtual:DEVICE_ON", displayId);
            mRequestedToBeAwake = true;
            if (mLockdownActive) {
                Slog.w(TAG, "Cannot wake up device during lockdown.");
                return;
            }
        }
        final long ident = Binder.clearCallingIdentity();
        try {
            wakeUpInternal(PowerManager.WAKE_REASON_POWER_BUTTON,
                    "android.server.companion.virtual:DEVICE_ON");
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
@@ -1614,6 +1621,34 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        }
    }

    void goToSleepInternal(@PowerManager.GoToSleepReason int reason) {
        final long now = SystemClock.uptimeMillis();
        synchronized (mVirtualDeviceLock) {
            for (int i = 0; i < mVirtualDisplays.size(); i++) {
                VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
                if (!wrapper.isTrusted() || wrapper.isMirror()) {
                    continue;
                }
                int displayId = mVirtualDisplays.keyAt(i);
                mPowerManager.goToSleep(displayId, now, reason, /* flags= */ 0);
            }
        }
    }

    void wakeUpInternal(@PowerManager.WakeReason int reason, String details) {
        final long now = SystemClock.uptimeMillis();
        synchronized (mVirtualDeviceLock) {
            for (int i = 0; i < mVirtualDisplays.size(); i++) {
                VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
                if (!wrapper.isTrusted() || wrapper.isMirror()) {
                    continue;
                }
                int displayId = mVirtualDisplays.keyAt(i);
                mPowerManager.wakeUp(now, reason, details, displayId);
            }
        }
    }

    /**
     * Release resources tied to virtual display owned by this VirtualDevice instance.
     *
+35 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.modules.expresslog.Counter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -129,6 +130,26 @@ public class VirtualDeviceManagerService extends SystemService {
                }
            };

    private class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
        final Set<Integer> mUsersInLockdown = new ArraySet<>();

        StrongAuthTracker(Context context) {
            super(context);
        }

        @Override
        public synchronized void onStrongAuthRequiredChanged(int userId) {
            if ((getStrongAuthForUser(userId) & STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN) > 0) {
                if (mUsersInLockdown.add(userId) && mUsersInLockdown.size() == 1) {
                    onLockdownChanged(true);
                }
            } else if (mUsersInLockdown.remove(userId) && mUsersInLockdown.isEmpty()) {
                onLockdownChanged(false);
            }
        }
    }
    private StrongAuthTracker mStrongAuthTracker;

    private final RemoteCallbackList<IVirtualDeviceListener> mVirtualDeviceListeners =
            new RemoteCallbackList<>();

@@ -201,6 +222,20 @@ public class VirtualDeviceManagerService extends SystemService {
                        + " will be available.");
            }
        }
        if (android.companion.virtualdevice.flags.Flags.deviceAwareDisplayPower()) {
            mStrongAuthTracker = new StrongAuthTracker(getContext());
            new LockPatternUtils(getContext()).registerStrongAuthTracker(mStrongAuthTracker);
        }
    }

    // Called when the global lockdown state changes, i.e. lockdown is considered active if any user
    // is in lockdown mode, and inactive if no users are in lockdown mode.
    void onLockdownChanged(boolean lockdownActive) {
        synchronized (mVirtualDeviceManagerLock) {
            for (int i = 0; i < mVirtualDevices.size(); i++) {
                mVirtualDevices.valueAt(i).onLockdownChanged(lockdownActive);
            }
        }
    }

    void onCameraAccessBlocked(int appUid) {