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

Commit 95d05138 authored by Robin Lee's avatar Robin Lee
Browse files

Make LogicalLight @Nullable: part two (internal)

Primarily refactors populateAvailableLights()

* breaks AIDL and HIDL logic into two small helpers
* stops going and inventing fake lights if we have the AIDL HAL.

Also reworks some LightsService internals

* move "system light" definition into the light class
* rename mLights -> mLightsByType (matching mLightsById)
* put the traceEnd() for "setLightState" in one final block

The way the HIDL HAL goes and invents fake lights hasn't been changed,
to avoid breaking HALs that didn't implement getLights() before.

Bug: 151113302
Test: atest LightsManagerTest
Test: atest LightsServiceTest
Test: atest google/perf/boottime/boottime-test
Change-Id: I23545586a2fa44ec656cd4c58df61970ce6db979
parent b9e44e50
Loading
Loading
Loading
Loading
+58 −68
Original line number Diff line number Diff line
@@ -52,8 +52,8 @@ public class LightsService extends SystemService {
    static final String TAG = "LightsService";
    static final boolean DEBUG = false;

    private LightImpl[] mLights = null;
    private SparseArray<LightImpl> mLightsById = null;
    private final LightImpl[] mLightsByType = new LightImpl[LightsManager.LIGHT_ID_COUNT];
    private final SparseArray<LightImpl> mLightsById = new SparseArray<>();

    private ILights mVintfLights = null;

@@ -96,8 +96,8 @@ public class LightsService extends SystemService {
            synchronized (LightsService.this) {
                final List<Light> lights = new ArrayList<Light>();
                for (int i = 0; i < mLightsById.size(); i++) {
                    HwLight hwLight = mLightsById.valueAt(i).getHwLight();
                    if (!isSystemLight(hwLight)) {
                    if (!mLightsById.valueAt(i).isSystemLight()) {
                        HwLight hwLight = mLightsById.valueAt(i).mHwLight;
                        lights.add(new Light(hwLight.id, hwLight.ordinal, hwLight.type));
                    }
                }
@@ -138,7 +138,7 @@ public class LightsService extends SystemService {

            synchronized (LightsService.this) {
                final LightImpl light = mLightsById.get(lightId);
                if (light == null || isSystemLight(light.getHwLight())) {
                if (light == null || light.isSystemLight()) {
                    throw new IllegalArgumentException("Invalid light: " + lightId);
                }
                return new LightState(light.getColor());
@@ -184,9 +184,8 @@ public class LightsService extends SystemService {
        private void checkRequestIsValid(int[] lightIds) {
            for (int i = 0; i < lightIds.length; i++) {
                final LightImpl light = mLightsById.get(lightIds[i]);
                final HwLight hwLight = light.getHwLight();
                Preconditions.checkState(light != null && !isSystemLight(hwLight),
                        "invalid lightId " + hwLight.id);
                Preconditions.checkState(light != null && !light.isSystemLight(),
                        "Invalid lightId " + lightIds[i]);
            }
        }

@@ -205,9 +204,8 @@ public class LightsService extends SystemService {
            }
            for (int i = 0; i < mLightsById.size(); i++) {
                LightImpl light = mLightsById.valueAt(i);
                HwLight hwLight = light.getHwLight();
                if (!isSystemLight(hwLight)) {
                    LightState state = states.get(hwLight.id);
                if (!light.isSystemLight()) {
                    LightState state = states.get(light.mHwLight.id);
                    if (state != null) {
                        light.setColor(state.getColor());
                    } else {
@@ -385,6 +383,7 @@ public class LightsService extends SystemService {
                int brightnessMode) {
            Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLightState(" + mHwLight.id + ", 0x"
                    + Integer.toHexString(color) + ")");
            try {
                if (mVintfLights != null) {
                    HwLightState lightState = new HwLightState();
                    lightState.color = color;
@@ -392,28 +391,29 @@ public class LightsService extends SystemService {
                    lightState.flashOnMs = onMS;
                    lightState.flashOffMs = offMS;
                    lightState.brightnessMode = (byte) brightnessMode;
                try {
                    mVintfLights.setLightState(mHwLight.id, lightState);
                } catch (RemoteException | UnsupportedOperationException ex) {
                    Slog.e(TAG, "Failed issuing setLightState", ex);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
                }
                } else {
                try {
                    setLight_native(mHwLight.id, color, mode, onMS, offMS, brightnessMode);
                }
            } catch (RemoteException | UnsupportedOperationException ex) {
                Slog.e(TAG, "Failed issuing setLightState", ex);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_POWER);
            }
        }
        }

        private boolean shouldBeInLowPersistenceMode() {
            return mVrModeEnabled && mUseLowPersistenceForVR;
        }

        private HwLight getHwLight() {
            return mHwLight;
        /**
         * Returns whether a light is system-use-only or should be accessible to
         * applications using the {@link android.hardware.lights.LightsManager} API.
         */
        private boolean isSystemLight() {
            // LIGHT_ID_COUNT comes from the 2.0 HIDL HAL and only contains system lights.
            // Newly-added lights are made available via the public LightsManager API.
            return (0 <= mHwLight.type && mHwLight.type < LightsManager.LIGHT_ID_COUNT);
        }

        private int getColor() {
@@ -451,37 +451,38 @@ public class LightsService extends SystemService {
    }

    private void populateAvailableLights(Context context) {
        mLights = new LightImpl[LightsManager.LIGHT_ID_COUNT];
        mLightsById = new SparseArray<>();

        if (mVintfLights != null) {
            try {
                for (HwLight availableLight : mVintfLights.getLights()) {
                    LightImpl light = new LightImpl(context, availableLight);
                    int type = (int) availableLight.type;
                    if (0 <= type && type < mLights.length && mLights[type] == null) {
                        mLights[type] = light;
            populateAvailableLightsFromAidl(context);
        } else {
            populateAvailableLightsFromHidl(context);
        }
                    mLightsById.put(availableLight.id, light);

        for (int i = mLightsById.size() - 1; i >= 0; i--) {
            final int type = mLightsById.keyAt(i);
            if (0 <= type && type < mLightsByType.length) {
                mLightsByType[type] = mLightsById.valueAt(i);
            }
            } catch (RemoteException ex) {
                Slog.e(TAG, "Unable to get lights for initialization", ex);
        }
    }

        // In the case where only the old HAL is available, all lights will be initialized here
        for (int i = 0; i < mLights.length; i++) {
            if (mLights[i] == null) {
                // The ordinal can be anything if there is only 1 light of each type. Set it to 1.
                HwLight light = new HwLight();
                light.id = (byte) i;
                light.ordinal = 1;
                light.type = (byte) i;

                mLights[i] = new LightImpl(context, light);
                mLightsById.put(i, mLights[i]);
    private void populateAvailableLightsFromAidl(Context context) {
        try {
            for (HwLight hwLight : mVintfLights.getLights()) {
                mLightsById.put(hwLight.id, new LightImpl(context, hwLight));
            }
        } catch (RemoteException ex) {
            Slog.e(TAG, "Unable to get lights from HAL", ex);
        }
    }

    private void populateAvailableLightsFromHidl(Context context) {
        for (int i = 0; i < mLightsByType.length; i++) {
            HwLight hwLight = new HwLight();
            hwLight.id = (byte) i;
            hwLight.ordinal = 1;
            hwLight.type = (byte) i;
            mLightsById.put(hwLight.id, new LightImpl(context, hwLight));
        }
    }

    @Override
@@ -505,25 +506,14 @@ public class LightsService extends SystemService {
    private final LightsManager mService = new LightsManager() {
        @Override
        public LogicalLight getLight(int lightType) {
            if (mLights != null && 0 <= lightType && lightType < mLights.length) {
                return mLights[lightType];
            if (mLightsByType != null && 0 <= lightType && lightType < mLightsByType.length) {
                return mLightsByType[lightType];
            } else {
                return null;
            }
        }
    };

    /**
     * Returns whether a light is system-use-only or should be accessible to
     * applications using the {@link android.hardware.lights.LightsManager} API.
     */
    private static boolean isSystemLight(HwLight light) {
        // LIGHT_ID_COUNT comes from the 2.0 HIDL HAL and only contains system
        // lights. Newly added lights will be made available via the
        // LightsManager API.
        return 0 <= light.type && light.type < LightsManager.LIGHT_ID_COUNT;
    }

    static native void setLight_native(int light, int color, int mode,
            int onMS, int offMS, int brightnessMode);
}