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

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

Update device_state_configuration.xml schema to support new properties

device_state_configuration.xml replaced flags with properties
to support the updated property based DeviceStateManager API's
and updates the default DeviceStateProvider implementation to
support these.

Also adds DeviceState.Configuration for system-server use to better
provide device state specific information to use in
DeviceStateManagerServicei. DeviceState.Configuration has support
for keeping the system properties and physical properties of a
provided state separate. This allows DeviceStateManager to provide
the correct physical property in the combined DeviceState to clients.

Flag: NA
Bug: 293636629
Test: DeviceStateProviderImplTest
Test: DeviceStateManagerServiceTest
Change-Id: I72a0de7bae787b8fb479ae1b987d8278df840983

Add DeviceStateConfiguration for system-server use

Change-Id: Icd8af7b994b7d57cb71c55bc4091f982dd79beea
parent ac919c27
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -1624,8 +1624,6 @@ package android.hardware.camera2.params {
package android.hardware.devicestate {

  @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceState {
    ctor @Deprecated public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, int);
    ctor public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, @NonNull java.util.Set<java.lang.Integer>);
    field public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8; // 0x8
  }

+197 −43
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@ import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;

import com.android.internal.util.Preconditions;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -268,68 +266,87 @@ public final class DeviceState {
    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
    public @interface DeviceStateProperties {}

    /** Unique identifier for the device state. */
    @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
    private final int mIdentifier;
    /** @hide */
    @IntDef(prefix = {"PROPERTY_"}, flag = true, value = {
            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED,
            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN,
            PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN
    })
    @Retention(RetentionPolicy.SOURCE)
    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
    public @interface PhysicalDeviceStateProperties {}

    /** @hide */
    @IntDef(prefix = {"PROPERTY_"}, flag = true, value = {
            PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
            PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
            PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
            PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
            PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST,
            PROPERTY_APP_INACCESSIBLE,
            PROPERTY_EMULATED_ONLY,
            PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
            PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
            PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP,
            PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE,
            PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY,
            PROPERTY_FEATURE_REAR_DISPLAY,
            PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT
    })
    @Retention(RetentionPolicy.SOURCE)
    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
    public @interface SystemDeviceStateProperties {}

    /** String description of the device state. */
    @NonNull
    private final String mName;
    private DeviceState.Configuration mDeviceStateConfiguration;

    @DeviceStateFlags
    private final int mFlags;

    private final Set<@DeviceStateProperties Integer> mProperties;
    /** @hide */
    public DeviceState(@NonNull DeviceState.Configuration deviceStateConfiguration) {
        mDeviceStateConfiguration = deviceStateConfiguration;
        mFlags = 0;
    }

    /** @hide */
    public DeviceState(
            @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
                    MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
            @NonNull String name,
            @NonNull Set<@DeviceStateProperties Integer> properties) {
        mDeviceStateConfiguration = new DeviceState.Configuration(identifier, name, properties,
                Collections.emptySet());
        mFlags = 0;
    }

    /**
     * @deprecated Deprecated in favor of {@link #DeviceState(int, String, Set)}
     * @hide
     */
    // TODO(b/325124054): Make non-default and remove deprecated callback methods.
    @TestApi
    @Deprecated
    public DeviceState(
            @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
                    MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
            @NonNull String name,
            @DeviceStateFlags int flags) {
        Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
                MAXIMUM_DEVICE_STATE_IDENTIFIER,
                "identifier");

        mIdentifier = identifier;
        mName = name;
        mDeviceStateConfiguration = new DeviceState.Configuration(identifier, name,
                Collections.emptySet(), Collections.emptySet());
        mFlags = flags;
        mProperties = Collections.emptySet();
    }

    /** @hide */
    @TestApi
    public DeviceState(
            @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
                    MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
            @NonNull String name,
            @NonNull Set<@DeviceStateProperties Integer> properties) {
        Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
                MAXIMUM_DEVICE_STATE_IDENTIFIER,
                "identifier");

        mIdentifier = identifier;
        mName = name;
        mProperties = Set.copyOf(properties);
        mFlags = 0;
    }

    /** Returns the unique identifier for the device state. */
    @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER)
    public int getIdentifier() {
        return mIdentifier;
        return mDeviceStateConfiguration.getIdentifier();
    }

    /** Returns a string description of the device state. */
    @NonNull
    public String getName() {
        return mName;
        return mDeviceStateConfiguration.getName();
    }

    /**
@@ -345,10 +362,13 @@ public final class DeviceState {

    @Override
    public String toString() {
        return "DeviceState{" + "identifier=" + mIdentifier + ", name='" + mName + '\''
                + ", app_accessible=" + !hasProperty(PROPERTY_APP_INACCESSIBLE)
        return "DeviceState{" + "identifier=" + mDeviceStateConfiguration.getIdentifier()
                + ", name='" + mDeviceStateConfiguration.getName() + '\''
                + ", app_accessible=" + !mDeviceStateConfiguration.getSystemProperties().contains(
                PROPERTY_APP_INACCESSIBLE)
                + ", cancel_when_requester_not_on_top="
                + hasProperty(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
                + mDeviceStateConfiguration.getSystemProperties().contains(
                PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
                + "}";
    }

@@ -357,14 +377,12 @@ public final class DeviceState {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DeviceState that = (DeviceState) o;
        return mIdentifier == that.mIdentifier
                && Objects.equals(mName, that.mName)
                && Objects.equals(mProperties, that.mProperties);
        return Objects.equals(mDeviceStateConfiguration, that.mDeviceStateConfiguration);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mIdentifier, mName, mProperties);
        return Objects.hash(mDeviceStateConfiguration);
    }

    /** Checks if a specific flag is set
@@ -381,7 +399,8 @@ public final class DeviceState {
     * Checks if a specific property is set on this state
     */
    public boolean hasProperty(@DeviceStateProperties int propertyToCheckFor) {
        return mProperties.contains(propertyToCheckFor);
        return mDeviceStateConfiguration.mSystemProperties.contains(propertyToCheckFor)
                || mDeviceStateConfiguration.mPhysicalProperties.contains(propertyToCheckFor);
    }

    /**
@@ -389,10 +408,145 @@ public final class DeviceState {
     */
    public boolean hasProperties(@NonNull @DeviceStateProperties int... properties) {
        for (int i = 0; i < properties.length; i++) {
            if (mProperties.contains(properties[i])) {
            if (!mDeviceStateConfiguration.mSystemProperties.contains(properties[i])
                    || !mDeviceStateConfiguration.mPhysicalProperties.contains(properties[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns the underlying {@link DeviceState.Configuration} object used to model the
     * device state.
     * @hide
     */
    public Configuration getConfiguration() {
        return mDeviceStateConfiguration;
    }

    /**
     * Detailed description of a {@link DeviceState} that includes separated sets of
     * {@link DeviceStateProperties} for properties that correspond to the state of the system when
     * the device is in this state, as well as physical properties that describe this state.
     *
     * Instantiation of this class should only be done by the system server, and clients of
     * {@link DeviceStateManager} will receive {@link DeviceState} objects.
     *
     * @see DeviceStateManager
     * @hide
     */
    public static class Configuration {
        /** Unique identifier for the device state. */
        @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
        private final int mIdentifier;

        /** String description of the device state. */
        @NonNull
        private final String mName;

        /** {@link Set} of system properties that apply to this state. */
        @NonNull
        private final Set<@SystemDeviceStateProperties Integer> mSystemProperties;

        /** {@link Set} of physical device properties that apply to this state. */
        @NonNull
        private final Set<@PhysicalDeviceStateProperties Integer> mPhysicalProperties;

        private Configuration(int identifier, @NonNull String name,
                @NonNull Set<@SystemDeviceStateProperties Integer> systemProperties,
                @NonNull Set<@PhysicalDeviceStateProperties Integer> physicalProperties) {
            mIdentifier = identifier;
            mName = name;
            mSystemProperties = systemProperties;
            mPhysicalProperties = physicalProperties;
        }

        /** Returns the unique identifier for the device state. */
        public int getIdentifier() {
            return mIdentifier;
        }

        /** Returns a string description of the device state. */
        @NonNull
        public String getName() {
            return mName;
        }

        /** Returns the {@link Set} of system properties that apply to this state. */
        @NonNull
        public Set<@SystemDeviceStateProperties Integer> getSystemProperties() {
            return mSystemProperties;
        }

        /** Returns the {@link Set} of physical device properties that apply to this state. */
        @NonNull
        public Set<@DeviceStateProperties Integer> getPhysicalProperties() {
            return mPhysicalProperties;
        }

        @Override
        public String toString() {
            return "DeviceState{" + "identifier=" + mIdentifier
                    + ", name='" + mName + '\''
                    + ", app_accessible=" + mSystemProperties.contains(PROPERTY_APP_INACCESSIBLE)
                    + ", cancel_when_requester_not_on_top="
                    + mSystemProperties.contains(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
                    + "}";
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            DeviceState.Configuration that = (DeviceState.Configuration) o;
            return mIdentifier == that.mIdentifier
                    && Objects.equals(mName, that.mName)
                    && Objects.equals(mSystemProperties, that.mSystemProperties)
                    && Objects.equals(mPhysicalProperties, that.mPhysicalProperties);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mIdentifier, mName, mSystemProperties, mPhysicalProperties);
        }

        /** @hide */
        public static class Builder {
            private final int mIdentifier;
            private final String mName;
            private Set<@SystemDeviceStateProperties Integer> mSystemProperties =
                    Collections.emptySet();
            private Set<@PhysicalDeviceStateProperties Integer> mPhysicalProperties =
                    Collections.emptySet();

            public Builder(int identifier, String name) {
                mIdentifier = identifier;
                mName = name;
            }

            /** Sets the system properties for this {@link DeviceState.Configuration.Builder} */
            public Builder setSystemProperties(
                    Set<@SystemDeviceStateProperties Integer> systemProperties) {
                mSystemProperties = systemProperties;
                return this;
            }

            /** Sets the system properties for this {@link DeviceState.Configuration.Builder} */
            public Builder setPhysicalProperties(
                    Set<@PhysicalDeviceStateProperties Integer> physicalProperties) {
                mPhysicalProperties = physicalProperties;
                return this;
            }

            /**
             * Returns a new {@link DeviceState.Configuration} whose values match the values set on
             * the builder.
             */
            public DeviceState.Configuration build() {
                return new DeviceState.Configuration(mIdentifier, mName, mSystemProperties,
                        mPhysicalProperties);
            }
        }
    }
}
+14 −8
Original line number Diff line number Diff line
@@ -30,16 +30,22 @@ object FoldableTestUtils {
        assumeTrue("Test should be launched on a foldable device",
            foldedDeviceStates.isNotEmpty())

        val folded =
            DeviceState(foldedDeviceStates.maxOrNull()!! /* identifier */,
                "" /* name */,
                emptySet() /* properties */)
        val unfolded =
            DeviceState(folded.identifier + 1 /* identifier */,
                "" /* name */,
                emptySet() /* properties */)
        val folded = getDeviceState(
            identifier = foldedDeviceStates.maxOrNull()!!
        )
        val unfolded = getDeviceState(
            identifier = folded.identifier + 1
        )
        return FoldableDeviceStates(folded = folded, unfolded = unfolded)
    }

    private fun getDeviceState(identifier: Int): DeviceState {
        return DeviceState(
            DeviceState.Configuration.Builder(
                identifier, "" /* name */
            ).build()
        )
    }
}

data class FoldableDeviceStates(val folded: DeviceState, val unfolded: DeviceState)
 No newline at end of file
+8 −7
Original line number Diff line number Diff line
@@ -19,7 +19,8 @@ package com.android.server.devicestate;
import static android.Manifest.permission.CONTROL_DEVICE_STATE;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS;
import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP;
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
@@ -408,7 +409,7 @@ public final class DeviceStateManagerService extends SystemService {
            mDeviceStates.clear();
            for (int i = 0; i < supportedDeviceStates.length; i++) {
                DeviceState state = supportedDeviceStates[i];
                if (state.hasFlag(FLAG_CANCEL_OVERRIDE_REQUESTS)) {
                if (state.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS)) {
                    hasTerminalDeviceState = true;
                }
                mDeviceStates.put(state.getIdentifier(), state);
@@ -453,7 +454,7 @@ public final class DeviceStateManagerService extends SystemService {
     * Returns the {@link DeviceState} with the supplied {@code identifier}, or {@code null} if
     * there is no device state with the identifier.
     */
    @Nullable
    @NonNull
    private Optional<DeviceState> getStateLocked(int identifier) {
        return Optional.ofNullable(mDeviceStates.get(identifier));
    }
@@ -468,7 +469,7 @@ public final class DeviceStateManagerService extends SystemService {
    private void setBaseState(int identifier) {
        synchronized (mLock) {
            final Optional<DeviceState> baseStateOptional = getStateLocked(identifier);
            if (!baseStateOptional.isPresent()) {
            if (baseStateOptional.isEmpty()) {
                throw new IllegalArgumentException("Base state is not supported");
            }

@@ -484,7 +485,7 @@ public final class DeviceStateManagerService extends SystemService {
            }
            mBaseState = Optional.of(baseState);

            if (baseState.hasFlag(FLAG_CANCEL_OVERRIDE_REQUESTS)) {
            if (baseState.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS)) {
                mOverrideRequestController.cancelOverrideRequest();
            }
            mOverrideRequestController.handleBaseStateChanged(identifier);
@@ -1023,7 +1024,7 @@ public final class DeviceStateManagerService extends SystemService {
    }

    private Set<Integer> readFoldedStates() {
        Set<Integer> foldedStates = new HashSet();
        Set<Integer> foldedStates = new HashSet<>();
        int[] mFoldedStatesArray = getContext().getResources().getIntArray(
                com.android.internal.R.array.config_foldedDeviceStates);
        for (int i = 0; i < mFoldedStatesArray.length; i++) {
@@ -1338,7 +1339,7 @@ public final class DeviceStateManagerService extends SystemService {
        }
        int identifier = mActiveOverride.get().getRequestedStateIdentifier();
        DeviceState deviceState = mDeviceStates.get(identifier);
        return deviceState.hasFlag(DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
        return deviceState.hasProperty(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
    }

    private class OverrideRequestScreenObserver implements
+2 −2
Original line number Diff line number Diff line
@@ -28,8 +28,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Responsible for providing the set of supported {@link DeviceState device states} as well as the
 * current device state.
 * Responsible for providing the set of supported {@link DeviceState.Configuration device states} as
 * well as the current device state.
 *
 * @see DeviceStatePolicy
 */
Loading