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

Commit a114eff4 authored by Kenneth Ford's avatar Kenneth Ford
Browse files

Migrate DeviceStateManager Clients to updated API

Flag: NA
Bug: 293636629
Test: PowerManagerServiceTest
Test: DisplayManagerServiceTest
Test: CentralSurfacesImplTest
Test: DeviceStateRotationLockSettingControllerTest
Test: DevicePostureControllerImplTest
Test: LogicalDisplayMapperTest
Change-Id: I46d0681ec837d950c26890c29e703a0e8a646745
parent 97c7930d
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.hardware.camera2.params.StreamConfiguration;
import android.hardware.camera2.utils.CameraIdAndSessionConfiguration;
import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
import android.hardware.camera2.utils.ExceptionUtils;
import android.hardware.devicestate.DeviceState;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.DisplayManager;
import android.os.Binder;
@@ -204,14 +205,12 @@ public final class CameraManager {
            mDeviceStateListeners.add(new WeakReference<>(listener));
        }

        @SuppressWarnings("FlaggedApi")
        @Override
        public final void onBaseStateChanged(int state) {
            handleStateChange(state);
        }

        @Override
        public final void onStateChanged(int state) {
            handleStateChange(state);
        public void onDeviceStateChanged(DeviceState state) {
            // Suppressing the FlaggedAPI warning as this specific API isn't new, just moved to
            // system API which requires it to be flagged.
            handleStateChange(state.getIdentifier());
        }
    }

+4 −4
Original line number Diff line number Diff line
@@ -115,8 +115,8 @@ public final class DeviceStateRequest {
         * requested state.
         * <p>
         * Guaranteed to be called after a call to
         * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)} with a state
         * matching the requested state.
         * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)} with a
         * state matching the requested state.
         */
        default void onRequestActivated(@NonNull DeviceStateRequest request) {}

@@ -124,7 +124,7 @@ public final class DeviceStateRequest {
         * Called to indicate the request has been temporarily suspended.
         * <p>
         * Guaranteed to be called before a call to
         * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
         * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)}.
         */
        default void onRequestSuspended(@NonNull DeviceStateRequest request) {}

@@ -134,7 +134,7 @@ public final class DeviceStateRequest {
         * DeviceStateRequest.Callback)}.
         * <p>
         * Guaranteed to be called before a call to
         * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
         * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)}.
         * <p>
         * Note: A call to {@link #onRequestSuspended(DeviceStateRequest)} is not guaranteed to
         * occur before this method.
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 android.hardware.devicestate;

import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;

import android.annotation.NonNull;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Utilities for {@link DeviceStateManager}.
 * @hide
 */
public class DeviceStateUtil {
    private DeviceStateUtil() { }

    /**
     * Returns the state identifier of the {@link DeviceState} that matches the
     * {@code currentState}s physical properties. This will return the identifier of the
     * {@link DeviceState} that matches the devices physical configuration.
     *
     * Returns {@link INVALID_DEVICE_STATE_IDENTIFIER} if there is no {@link DeviceState} in the
     * provided list of {@code supportedStates} that matches.
     * @hide
     */
    public static int calculateBaseStateIdentifier(@NonNull DeviceState currentState,
            @NonNull List<DeviceState> supportedStates) {
        DeviceState.Configuration stateConfiguration = currentState.getConfiguration();
        for (int i = 0; i < supportedStates.size(); i++) {
            DeviceState stateToCompare = supportedStates.get(i);
            if (stateToCompare.getConfiguration().getPhysicalProperties().isEmpty()) {
                continue;
            }
            if (isDeviceStateMatchingPhysicalProperties(stateConfiguration.getPhysicalProperties(),
                    supportedStates.get(i))) {
                return supportedStates.get(i).getIdentifier();
            }
        }
        return INVALID_DEVICE_STATE_IDENTIFIER;
    }

    /**
     * Returns if the physical properties provided, matches the same physical properties on the
     * provided {@link DeviceState}.
     */
    private static boolean isDeviceStateMatchingPhysicalProperties(
            Set<@DeviceState.PhysicalDeviceStateProperties Integer> physicalProperties,
            DeviceState state) {
        Iterator<@DeviceState.PhysicalDeviceStateProperties Integer> iterator =
                physicalProperties.iterator();
        while (iterator.hasNext()) {
            if (!state.hasProperty(iterator.next())) {
                return false;
            }
        }
        return true;
    }

}
+27 −33
Original line number Diff line number Diff line
@@ -19,13 +19,14 @@ package androidx.window.common;
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;

import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN;
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE;
import static androidx.window.common.CommonFoldingFeature.parseListFromString;

import android.annotation.NonNull;
import android.content.Context;
import android.hardware.devicestate.DeviceState;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
import android.hardware.devicestate.DeviceStateUtil;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseIntArray;
@@ -54,29 +55,27 @@ public final class DeviceStateManagerFoldingFeatureProducer
    private static final boolean DEBUG = false;

    /**
     * Emulated device state {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)} to
     * Emulated device state
     * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)} to
     * {@link CommonFoldingFeature.State} map.
     */
    private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();

    /**
     * Emulated device state received via
     * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
     * "Emulated" states differ from "base" state in the sense that they may not correspond 1:1 with
     * physical device states. They represent the state of the device when various software
     * features and APIs are applied. The emulated states generally consist of all "base" states,
     * but may have additional states such as "concurrent" or "rear display". Concurrent mode for
     * example is activated via public API and can be active in both the "open" and "half folded"
     * device states.
     * Device state received via
     * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)}.
     * The identifier returned through {@link DeviceState#getIdentifier()} may not correspond 1:1
     * with the physical state of the device. This could correspond to the system state of the
     * device when various software features or overrides are applied. The emulated states generally
     * consist of all "base" states, but may have additional states such as "concurrent" or
     * "rear display". Concurrent mode for example is activated via public API and can be active in
     * both the "open" and "half folded" device states.
     */
    private int mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
    private DeviceState mCurrentDeviceState = new DeviceState(
            new DeviceState.Configuration.Builder(INVALID_DEVICE_STATE_IDENTIFIER,
                    "INVALID").build());

    /**
     * Base device state received via
     * {@link DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int)}.
     * "Base" in this context means the "physical" state of the device.
     */
    private int mCurrentBaseDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
    private List<DeviceState> mSupportedStates;

    @NonNull
    private final RawFoldingFeatureProducer mRawFoldSupplier;
@@ -85,22 +84,11 @@ public final class DeviceStateManagerFoldingFeatureProducer

    private final DeviceStateCallback mDeviceStateCallback = new DeviceStateCallback() {
        @Override
        public void onStateChanged(int state) {
        public void onDeviceStateChanged(@NonNull DeviceState state) {
            mCurrentDeviceState = state;
            mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer
                    .this::notifyFoldingFeatureChange);
        }

        @Override
        public void onBaseStateChanged(int state) {
            mCurrentBaseDeviceState = state;

            if (mDeviceStateToPostureMap.get(mCurrentDeviceState)
                    == COMMON_STATE_USE_BASE_STATE) {
                mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer
                        .this::notifyFoldingFeatureChange);
            }
        }
    };

    public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context,
@@ -109,6 +97,7 @@ public final class DeviceStateManagerFoldingFeatureProducer
        mRawFoldSupplier = rawFoldSupplier;
        String[] deviceStatePosturePairs = context.getResources()
                .getStringArray(R.array.config_device_state_postures);
        mSupportedStates = deviceStateManager.getSupportedDeviceStates();
        boolean isHalfOpenedSupported = false;
        for (String deviceStatePosturePair : deviceStatePosturePairs) {
            String[] deviceStatePostureMapping = deviceStatePosturePair.split(":");
@@ -168,7 +157,7 @@ public final class DeviceStateManagerFoldingFeatureProducer
     */
    private boolean isCurrentStateValid() {
        // If the device state is not found in the map, indexOfKey returns a negative number.
        return mDeviceStateToPostureMap.indexOfKey(mCurrentDeviceState) >= 0;
        return mDeviceStateToPostureMap.indexOfKey(mCurrentDeviceState.getIdentifier()) >= 0;
    }

    @Override
@@ -177,7 +166,9 @@ public final class DeviceStateManagerFoldingFeatureProducer
        if (hasListeners()) {
            mRawFoldSupplier.addDataChangedCallback(this::notifyFoldingFeatureChange);
        } else {
            mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
            mCurrentDeviceState = new DeviceState(
                    new DeviceState.Configuration.Builder(INVALID_DEVICE_STATE_IDENTIFIER,
                            "INVALID").build());
            mRawFoldSupplier.removeDataChangedCallback(this::notifyFoldingFeatureChange);
        }
    }
@@ -251,10 +242,13 @@ public final class DeviceStateManagerFoldingFeatureProducer
    @CommonFoldingFeature.State
    private int currentHingeState() {
        @CommonFoldingFeature.State
        int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState, COMMON_STATE_UNKNOWN);
        int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState.getIdentifier(),
                COMMON_STATE_UNKNOWN);

        if (posture == CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE) {
            posture = mDeviceStateToPostureMap.get(mCurrentBaseDeviceState, COMMON_STATE_UNKNOWN);
            posture = mDeviceStateToPostureMap.get(
                    DeviceStateUtil.calculateBaseStateIdentifier(mCurrentDeviceState,
                            mSupportedStates), COMMON_STATE_UNKNOWN);
        }

        return posture;
+20 −5
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STA

import android.app.Activity;
import android.content.Context;
import android.hardware.devicestate.DeviceState;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.devicestate.DeviceStateRequest;
import android.hardware.display.DisplayManager;
@@ -40,6 +41,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;

@@ -101,7 +103,9 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
        mDisplayManager = context.getSystemService(DisplayManager.class);
        mExecutor = context.getMainExecutor();

        mCurrentSupportedDeviceStates = mDeviceStateManager.getSupportedStates();
        // TODO(b/329436166): Update the usage of device state manager API's
        mCurrentSupportedDeviceStates = getSupportedStateIdentifiers(
                mDeviceStateManager.getSupportedDeviceStates());
        mFoldedDeviceStates = context.getResources().getIntArray(
                R.array.config_foldedDeviceStates);

@@ -446,9 +450,10 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
    }

    @Override
    public void onSupportedStatesChanged(int[] supportedStates) {
    public void onSupportedStatesChanged(@NonNull List<DeviceState> supportedStates) {
        synchronized (mLock) {
            mCurrentSupportedDeviceStates = supportedStates;
            // TODO(b/329436166): Update the usage of device state manager API's
            mCurrentSupportedDeviceStates = getSupportedStateIdentifiers(supportedStates);
            updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
            updateRearDisplayPresentationStatusListeners(
                    getCurrentRearDisplayPresentationModeStatus());
@@ -456,9 +461,10 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
    }

    @Override
    public void onStateChanged(int state) {
    public void onDeviceStateChanged(@NonNull DeviceState state) {
        synchronized (mLock) {
            mCurrentDeviceState = state;
            // TODO(b/329436166): Update the usage of device state manager API's
            mCurrentDeviceState = state.getIdentifier();
            updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
            updateRearDisplayPresentationStatusListeners(
                    getCurrentRearDisplayPresentationModeStatus());
@@ -482,6 +488,15 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
        return WindowAreaComponent.STATUS_AVAILABLE;
    }

    // TODO(b/329436166): Remove and update the usage of device state manager API's
    private int[] getSupportedStateIdentifiers(@NonNull List<DeviceState> states) {
        int[] identifiers = new int[states.size()];
        for (int i = 0; i < states.size(); i++) {
            identifiers[i] = states.get(i).getIdentifier();
        }
        return identifiers;
    }

    /**
     * Helper method to determine if a rear display session is currently active by checking
     * if the current device state is that which corresponds to {@code mRearDisplayState}.
Loading