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

Commit 2dd3fdce authored by Darryl Johnson's avatar Darryl Johnson Committed by Android (Google) Code Review
Browse files

Merge "Don't throw exception if DeviceStateProviderImpl can't find required sensor." into sc-dev

parents f4baaf8a f89a5e33
Loading
Loading
Loading
Loading
+37 −13
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider,
    private static final String TAG = "DeviceStateProviderImpl";

    private static final BooleanSupplier TRUE_BOOLEAN_SUPPLIER = () -> true;
    private static final BooleanSupplier FALSE_BOOLEAN_SUPPLIER = () -> false;

    @VisibleForTesting
    static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE,
@@ -152,7 +153,7 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider,
    private final DeviceState[] mOrderedStates;
    // Map of state identifier to a boolean supplier that returns true when all required conditions
    // are met for the device to be in the state.
    private final SparseArray<BooleanSupplier> mStateConditions;
    private final SparseArray<BooleanSupplier> mStateConditions = new SparseArray<>();

    @Nullable
    @GuardedBy("mLock")
@@ -177,6 +178,11 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider,
        Arrays.sort(orderedStates, Comparator.comparingInt(DeviceState::getIdentifier));
        mOrderedStates = orderedStates;

        setStateConditions(deviceStates, stateConditions);
    }

    private void setStateConditions(@NonNull List<DeviceState> deviceStates,
            @NonNull List<Conditions> stateConditions) {
        // Whether or not this instance should register to receive lid switch notifications from
        // InputManagerInternal. If there are no device state conditions that are based on the lid
        // switch there is no need to register for a callback.
@@ -185,7 +191,6 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider,
        // The set of Sensor(s) that this instance should register to receive SensorEvent(s) from.
        final ArraySet<Sensor> sensorsToListenTo = new ArraySet<>();

        mStateConditions = new SparseArray<>();
        for (int i = 0; i < stateConditions.size(); i++) {
            final int state = deviceStates.get(i).getIdentifier();
            final Conditions conditions = stateConditions.get(i);
@@ -194,12 +199,20 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider,
                continue;
            }

            // Whether or not all the required hardware components could be found that match the
            // requirements from the config.
            boolean allRequiredComponentsFound = true;
            // Whether or not this condition requires the lid switch.
            boolean lidSwitchRequired = false;
            // Set of sensors required for this condition.
            ArraySet<Sensor> sensorsRequired = new ArraySet<>();

            List<BooleanSupplier> suppliers = new ArrayList<>();

            LidSwitchCondition lidSwitchCondition = conditions.getLidSwitch();
            if (lidSwitchCondition != null) {
                suppliers.add(new LidSwitchBooleanSupplier(lidSwitchCondition.getOpen()));
                shouldListenToLidSwitch = true;
                lidSwitchRequired = true;
            }

            List<SensorCondition> sensorConditions = conditions.getSensor();
@@ -210,14 +223,20 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider,

                final Sensor foundSensor = findSensor(expectedSensorType, expectedSensorName);
                if (foundSensor == null) {
                    throw new IllegalStateException("Failed to find Sensor with type: "
                            + expectedSensorType + " and name: " + expectedSensorName);
                    Slog.e(TAG, "Failed to find Sensor with type: " + expectedSensorType
                            + " and name: " + expectedSensorName);
                    allRequiredComponentsFound = false;
                    break;
                }

                suppliers.add(new SensorBooleanSupplier(foundSensor, sensorCondition.getValue()));
                sensorsToListenTo.add(foundSensor);
                sensorsRequired.add(foundSensor);
            }

            if (allRequiredComponentsFound) {
                shouldListenToLidSwitch |= lidSwitchRequired;
                sensorsToListenTo.addAll(sensorsRequired);

                if (suppliers.size() > 1) {
                    mStateConditions.put(state, new AndBooleanSupplier(suppliers));
                } else if (suppliers.size() > 0) {
@@ -227,6 +246,11 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider,
                    // There are no conditions for this state. Default to always true.
                    mStateConditions.put(state, TRUE_BOOLEAN_SUPPLIER);
                }
            } else {
                // Failed to setup this condition. This can happen if a sensor is missing. Default
                // this state to always false.
                mStateConditions.put(state, FALSE_BOOLEAN_SUPPLIER);
            }
        }

        if (shouldListenToLidSwitch) {
+50 −0
Original line number Diff line number Diff line
@@ -307,6 +307,56 @@ public final class DeviceStateProviderImplTest {
        assertEquals(1, mIntegerCaptor.getValue().intValue());
    }

    @Test
    public void create_invalidSensor() throws Exception {
        Sensor sensor = newSensor("sensor", Sensor.STRING_TYPE_HINGE_ANGLE);
        when(mSensorManager.getSensorList(anyInt())).thenReturn(List.of());

        String configString = "<device-state-config>\n"
                + "    <device-state>\n"
                + "        <identifier>1</identifier>\n"
                + "        <name>CLOSED</name>\n"
                + "        <conditions>\n"
                + "            <sensor>\n"
                + "                <type>" + sensor.getStringType() + "</type>\n"
                + "                <name>" + sensor.getName() + "</name>\n"
                + "                <value>\n"
                + "                    <max>90</max>\n"
                + "                </value>\n"
                + "            </sensor>\n"
                + "        </conditions>\n"
                + "    </device-state>\n"
                + "    <device-state>\n"
                + "        <identifier>2</identifier>\n"
                + "        <name>HALF_OPENED</name>\n"
                + "        <conditions>\n"
                + "            <sensor>\n"
                + "                <type>" + sensor.getStringType() + "</type>\n"
                + "                <name>" + sensor.getName() + "</name>\n"
                + "                <value>\n"
                + "                    <min-inclusive>90</min-inclusive>\n"
                + "                    <max>180</max>\n"
                + "                </value>\n"
                + "            </sensor>\n"
                + "        </conditions>\n"
                + "    </device-state>\n"
                + "</device-state-config>\n";
        DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
        DeviceStateProviderImpl provider = DeviceStateProviderImpl.createFromConfig(mContext,
                config);

        DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
        provider.setListener(listener);

        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
        assertArrayEquals(
                new DeviceState[]{ new DeviceState(1, "CLOSED"), new DeviceState(2, "HALF_OPENED"),
                        }, mDeviceStateArrayCaptor.getValue());
        // onStateChanged() should be called because the provider could not find the sensor.
        verify(listener).onStateChanged(mIntegerCaptor.capture());
        assertEquals(1, mIntegerCaptor.getValue().intValue());
    }

    private static Sensor newSensor(String name, String type) throws Exception {
        Constructor<Sensor> constructor = Sensor.class.getDeclaredConstructor();
        constructor.setAccessible(true);