基于 Light 介绍安卓 8.0 HAL 变化

/frameworks/base/services/core/java/com/android/server/lights/LightsService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

public class LightsService extends SystemService {
    static final String TAG = "LightsService";
@Nullable
    private final Supplier<ILights> mVintfLights;
    ... ...
    private final class LightsManagerBinderService extends ILightsManager.Stub {
        ... ...
    }
    ... ...
    public LightsService(Context context) {
        this(context, new VintfHalCache(), Looper.myLooper());
    }

@VisibleForTesting
    LightsService(Context context, Supplier<ILights> service, Looper looper) {
        super(context);
        mH = new Handler(looper);
        mVintfLights = service.get() != null ? service : null;

populateAvailableLights(context);
        mManagerService = new LightsManagerBinderService();
    }

private void populateAvailableLights(Context context) {
        if (mVintfLights != null) {
            populateAvailableLightsFromAidl(context);
        } else {
            populateAvailableLightsFromHidl(context);
        }

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);
            }
        }
    }

private void populateAvailableLightsFromAidl(Context context) {
        try {
            for (HwLight hwLight : mVintfLights.get().getLights()) {
                mLightsById.put(hwLight.id, new LightImpl(context, hwLight));
            }
        } catch (RemoteException ex) {
            Slog.e(TAG, "Unable to get lights from HAL", ex);
        }
    }
    ... ...
    private final class LightImpl extends LogicalLight {
        .... ....
        @Override
        public void setBrightness(float brightness) {
            setBrightness(brightness, BRIGHTNESS_MODE_USER);
        }

@Override
        public void setBrightness(float brightness, int brightnessMode) {
            if (Float.isNaN(brightness)) {
                Slog.w(TAG, "Brightness is not valid: " + brightness);
                return;
            }
            synchronized (this) {
                // LOW_PERSISTENCE cannot be manually set
                if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
                    Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mHwLight.id
                            + ": brightness=" + brightness);
                    return;
                }
                // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
                // right now we just fall back to the old path through Lights brightessMode is
                // anything but USER or the device shouldBeInLowPersistenceMode().
                if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode()
                        && mSurfaceControlMaximumBrightness == 255) {
                    // New system
                    // TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the
                    // reason we enforce 255 right now is to stay consistent with the old path. In
                    // the future, the framework should be refactored so that brightness is a float
                    // between 0.0f and 1.0f, and the actual number of supported brightness levels
                    // is determined in the device-specific implementation.
                    if (DEBUG) {
                        Slog.d(TAG, "Using new setBrightness path!");
                    }
                    SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
                } else {
                    // Old system
                    int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(
                            getContext(), brightness);
                    int color = brightnessInt & 0x000000ff;
                    color = 0xff000000 | (color << 16) | (color << 8) | color;
                    setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
                }
            }
        }

private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
            if (shouldBeInLowPersistenceMode()) {
                brightnessMode = BRIGHTNESS_MODE_LOW_PERSISTENCE;
            } else if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
                brightnessMode = mLastBrightnessMode;
            }

if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS ||
                    offMS != mOffMS || mBrightnessMode != brightnessMode) {
                if (DEBUG) {
                    Slog.v(TAG, "setLight #" + mHwLight.id + ": color=#"
                            + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
                }
                mInitialized = true;
                mLastColor = mColor;
                mColor = color;
                mMode = mode;
                mOnMS = onMS;
                mOffMS = offMS;
                mBrightnessMode = brightnessMode;
                setLightUnchecked(color, mode, onMS, offMS, brightnessMode);
            }
        }

private void setLightUnchecked(int color, int mode, int onMS, int offMS,
                int brightnessMode) {
            Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLightState(" + mHwLight.id + ", 0x"
                    + Integer.toHexString(color) + ")");
            //add for bug1296210
            if (!mSprdLightsUtils.isBatteryOpenWhenNotificationCome(mHwLight.id, color)) {
                try {
                    if (mVintfLights != null) {
                        HwLightState lightState = new HwLightState();
                        lightState.color = color;
                        lightState.flashMode = (byte) mode;
                        lightState.flashOnMs = onMS;
                        lightState.flashOffMs = offMS;
                        lightState.brightnessMode = (byte) brightnessMode;
                        mVintfLights.get().setLightState(mHwLight.id, lightState);  //aidl
                    } else {
                        setLight_native(mHwLight.id, color, mode, onMS, offMS, brightnessMode); //jni->hidl->hal
                    }
                } catch (RemoteException | UnsupportedOperationException ex) {
                    Slog.e(TAG, "Failed issuing setLightState", ex);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
                }
            }
        }
        ... ...
    }
    ... ...
    static native void setLight_native(int light, int color, int mode,
            int onMS, int offMS, int brightnessMode);
}

一、通过jni的方式:

1. 8.0之前jni->hal

\frameworks\base\services\core\Android.mk

LOCAL_MODULE := services.core

\frameworks\base\services\core\jni\Android.mk

LOCAL_SRC_FILES += \

$(LOCAL_REL_DIR)/com_android_server_lights_LightsService.cpp \

 ... ...

/frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

/*
 * Copyright (C) 2009 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.
 */

#define LOG_TAG "LightsService"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"

#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/lights.h>  //hal层也include了这个

#include <stdio.h>

namespace android
{

// These values must correspond with the LIGHT_ID constants in
// LightsService.java
enum {
    LIGHT_INDEX_BACKLIGHT = 0,
    LIGHT_INDEX_KEYBOARD = 1,
    LIGHT_INDEX_BUTTONS = 2,
    LIGHT_INDEX_BATTERY = 3,
    LIGHT_INDEX_NOTIFICATIONS = 4,
    LIGHT_INDEX_ATTENTION = 5,
    LIGHT_INDEX_BLUETOOTH = 6,
    LIGHT_INDEX_WIFI = 7,
    LIGHT_COUNT
};

struct Devices {
    light_device_t* lights[LIGHT_COUNT];
};

static light_device_t* get_device(hw_module_t* module, char const* name)
{
    int err;
    hw_device_t* device;
    err = module->methods->open(module, name, &device);  //将二级指针&device传给hal层
    if (err == 0) {                         //hardware/libhardware/include/hardware/lights.h
        return (light_device_t*)device; //强转为与hal层同一类型
    } else {
        return NULL;
    }
}

static jlong init_native(JNIEnv* /* env */, jobject /* clazz */)
{
    int err;
    hw_module_t* module;
    Devices* devices;
    
    devices = (Devices*)malloc(sizeof(Devices));

err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    if (err == 0) {
        devices->lights[LIGHT_INDEX_BACKLIGHT]
                = get_device(module, LIGHT_ID_BACKLIGHT);  //保存着hal层赋值的具体函数指针
        devices->lights[LIGHT_INDEX_KEYBOARD]
                = get_device(module, LIGHT_ID_KEYBOARD);
        devices->lights[LIGHT_INDEX_BUTTONS]
                = get_device(module, LIGHT_ID_BUTTONS);
        devices->lights[LIGHT_INDEX_BATTERY]
                = get_device(module, LIGHT_ID_BATTERY);
        devices->lights[LIGHT_INDEX_NOTIFICATIONS]
                = get_device(module, LIGHT_ID_NOTIFICATIONS);
        devices->lights[LIGHT_INDEX_ATTENTION]
                = get_device(module, LIGHT_ID_ATTENTION);
        devices->lights[LIGHT_INDEX_BLUETOOTH]
                = get_device(module, LIGHT_ID_BLUETOOTH);
        devices->lights[LIGHT_INDEX_WIFI]
                = get_device(module, LIGHT_ID_WIFI);
    } else {
        memset(devices, 0, sizeof(Devices));
    }

return (jlong)devices;
}

static void finalize_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr)
{
    Devices* devices = (Devices*)ptr;
    if (devices == NULL) {
        return;
    }

free(devices);
}

static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
        jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
{
    Devices* devices = (Devices*)ptr;
    light_state_t state;

if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
        return ;
    }

uint32_t version = devices->lights[light]->common.version;

memset(&state, 0, sizeof(light_state_t));

if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
        if (light != LIGHT_INDEX_BACKLIGHT) {
            ALOGE("Cannot set low-persistence mode for non-backlight device.");
            return;
        }
        if (version < LIGHTS_DEVICE_API_VERSION_2_0) {
            // HAL impl has not been upgraded to support this.
            return;
        }
    } else {
        // Only set non-brightness settings when not in low-persistence mode
        state.color = colorARGB;
        state.flashMode = flashMode;
        state.flashOnMS = onMS;
        state.flashOffMS = offMS;
    }

state.brightnessMode = brightnessMode;

{
        ALOGD_IF_SLOW(50, "Excessive delay setting light");
        devices->lights[light]->set_light(devices->lights[light], &state); //调用hal层函数指针设置背光
    }
}

static const JNINativeMethod method_table[] = {
    { "init_native", "()J", (void*)init_native },
    { "finalize_native", "(J)V", (void*)finalize_native },
    { "setLight_native", "(JIIIIII)V", (void*)setLight_native },
};

int register_android_server_LightsService(JNIEnv *env)
{
    return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
            method_table, NELEM(method_table));
}

};

2. 8.0之后jni->HIDL->HAL

JNI:

\frameworks\base\services\core\jni\Android.mk

cc_library_static {

name: "libservices.core",

... ...

srcs: [

":lib_alarmManagerService_native",

  "com_android_server_lights_LightsService.cpp",

  ... ...

  ":lib_networkStatsFactory_native",

}

/frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

#define LOG_TAG "LightsService"
#include <android/hardware/light/2.0/ILight.h> //对应着ILight.hal
#include <android/hardware/light/2.0/types.h>  //对应着types.hal
... ...
namespace android {

using Brightness = ::android::hardware::light::V2_0::Brightness;
using Flash      = ::android::hardware::light::V2_0::Flash;
using ILight     = ::android::hardware::light::V2_0::ILight;
using LightState = ::android::hardware::light::V2_0::LightState;
using Status     = ::android::hardware::light::V2_0::Status;
using Type       = ::android::hardware::light::V2_0::Type;
template<typename T>
using Return     = ::android::hardware::Return<T>;

static bool sLightSupported = true;
... ...
static void setLight_native(
        JNIEnv* /* env */,
        jobject /* clazz */,
        jint light,
        jint colorARGB,
        jint flashMode,
        jint onMS,
        jint offMS,
        jint brightnessMode) {

if (!sLightSupported) {
        return;
    }

if (!validate(light, flashMode, brightnessMode)) {
        return;
    }

Type type = static_cast<Type>(light);
    LightState state = constructState(
        colorARGB, flashMode, onMS, offMS, brightnessMode);

{
        android::base::Timer t;
        sp<ILight> hal = ILight::getService();  //获取hidl服务
        if (hal == nullptr) {
            sLightSupported = false;
            return;
        }
        Return<Status> ret = hal->setLight(type, state);
        processReturn(ret, type, state);
        if (t.duration() > 50ms) ALOGD("Excessive delay setting light");
    }
}

static const JNINativeMethod method_table[] = {
    { "setLight_native", "(IIIIII)V", (void*)setLight_native },
};

int register_android_server_LightsService(JNIEnv *env) {
    return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
            method_table, NELEM(method_table));
}

};

HIDL interface:

/hardware/interfaces/light/2.0/Android.bp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

// This file is autogenerated by hidl-gen -Landroidbp.

hidl_interface {
    name: "android.hardware.light@2.0",
    root: "android.hardware",
    vndk: {
        enabled: true,
    },
    srcs: [
        "types.hal",
        "ILight.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    gen_java: true,
}

/hardware/interfaces/light/2.0/types.hal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

package android.hardware.light@2.0;
... ...
/**
 * These light IDs correspond to logical lights, not physical.
 * So for example, if your INDICATOR light is in line with your
 * BUTTONS, it might make sense to also light the INDICATOR
 * light to a reasonable color when the BUTTONS are lit.
 */
enum Type : int32_t {
    BACKLIGHT,
    KEYBOARD,
    BUTTONS,
    BATTERY,
    NOTIFICATIONS,
    ATTENTION,
    BLUETOOTH,
    WIFI,

COUNT,
};

/**
 * The parameters that can be set for a given light.
 *
 * Not all lights must support all parameters. If you
 * can do something backward-compatible, do it.
 */
struct LightState {
    /**
     * The color of the LED in ARGB.
     *
     * Do your best here.
     *   - If your light can only do red or green, if they ask for blue,
     *     you should do green.
     *   - If you can only do a brightness ramp, then use this formula:
     *      unsigned char brightness = ((77*((color>>16)&0x00ff))
     *              + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
     *   - If you can only do on or off, 0 is off, anything else is on.
     *
     * The high byte should be ignored. Callers will set it to 0xff (which
     * would correspond to 255 alpha).
     */
    uint32_t color;

/**
     * To flash the light at a given rate, set flashMode to LIGHT_FLASH_TIMED,
     * and then flashOnMS should be set to the number of milliseconds to turn
     * the light on, followed by the number of milliseconds to turn the light
     * off.
     */
    Flash flashMode;

int32_t flashOnMs;
    int32_t flashOffMs;

Brightness brightnessMode;
};

/hardware/interfaces/light/2.0/ILight.hal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

package android.hardware.light@2.0;

interface ILight {

/**
     * Set the provided lights to the provided values.
     *
     * @param type logical light to set
     * @param state describes what the light should look like.
     * @return status result of applying state transformation.
     */
    setLight(Type type, LightState state) generates (Status status);

/**
     * Discover what indicator lights are available.
     *
     * @return types list of available lights
     */
    getSupportedTypes() generates (vec<Type> types);

};

HIDL:

/vendor/mediatek/proprietary/hardware/liblights/2.0/default/android.hardware.light@2.0-service-mediatek.rc

service light-hal-2-0 /vendor/bin/hw/android.hardware.light@2.0-service-mediatek

interface android.hardware.light@2.0::ILight default

class hal

user system

group system

# shutting off lights while powering-off

shutdown critical

/vendor/mediatek/proprietary/hardware/liblights/2.0/default/service.cpp

1
2
3
4
5
6
7
8
9
10
11
12

#define NDEBUG 1
#define LOG_TAG "android.hardware.light@2.0-service-mediatek"

#include <android/hardware/light/2.0/ILight.h>
#include <hidl/LegacySupport.h>

using android::hardware::light::V2_0::ILight;
using android::hardware::defaultPassthroughServiceImplementation;

int main() {
    return defaultPassthroughServiceImplementation<ILight>();
}

/vendor/mediatek/proprietary/hardware/liblights/2.0/default/Android.mk

LOCAL_PATH := $(call my-dir)    //用于返回当前mk文件路径,由build system提供

include $(CLEAR_VARS)

LOCAL_MODULE_RELATIVE_PATH := hw

LOCAL_MODULE := android.hardware.light@2.0-service-mediatek

LOCAL_INIT_RC := android.hardware.light@2.0-service-mediatek.rc

LOCAL_SRC_FILES := service.cpp     //生成在\out\target\product\tb8321p3_bsp\vendor\bin\hw\android.hardware.light@2.0-service-mediatek

... ...

include $(BUILD_EXECUTABLE)       //对应Android.bp的 cc_binary{

include $(CLEAR_VARS)  //让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。

LOCAL_MODULE := android.hardware.light@2.0-impl-mediatek

LOCAL_MODULE_RELATIVE_PATH := hw   //生成在\out\target\product\tb8321p3_bsp\vendor\lib\hw\android.hardware.light@2.0-impl-mediatek.so

LOCAL_SRC_FILES := \

Light.cpp \

... ...

include $(BUILD_SHARED_LIBRARY)     //对应Android.bp的 cc_library_shared{

/vendor/mediatek/proprietary/hardware/liblights/2.0/default/Light.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

#ifndef ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
#define ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H

#include <android/hardware/light/2.0/ILight.h>  //对应着ILight.hal
#include <hardware/hardware.h>
#include <hardware/lights.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
#include <map>

#include <cutils/log.h>

namespace android {
namespace hardware {
namespace light {
namespace V2_0 {
namespace implementation {

using ::android::hardware::light::V2_0::ILight;
using ::android::hardware::light::V2_0::LightState;
using ::android::hardware::light::V2_0::Status;
using ::android::hardware::light::V2_0::Type;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;

struct Light : public ILight {
    Light(std::map<Type, light_device_t*> &&lights);

// Methods from ::android::hardware::light::V2_0::ILight follow.
    Return<Status> setLight(Type type, const LightState& state)  override;
    Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb)  override;

private:
    std::map<Type, light_device_t*> mLights;
};

extern "C" ILight* HIDL_FETCH_ILight(const char* name);

}  // namespace implementation
}  // namespace V2_0
}  // namespace light
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H

/vendor/mediatek/proprietary/hardware/liblights/2.0/default/Light.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

/*
 * Copyright (C) 2016 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.
 */
#include "Light.h"

namespace android {
namespace hardware {
namespace light {
namespace V2_0 {
namespace implementation {

static_assert(LIGHT_FLASH_NONE == static_cast<int>(Flash::NONE),
    "Flash::NONE must match legacy value.");
static_assert(LIGHT_FLASH_TIMED == static_cast<int>(Flash::TIMED),
    "Flash::TIMED must match legacy value.");
static_assert(LIGHT_FLASH_HARDWARE == static_cast<int>(Flash::HARDWARE),
    "Flash::HARDWARE must match legacy value.");

static_assert(BRIGHTNESS_MODE_USER == static_cast<int>(Brightness::USER),
    "Brightness::USER must match legacy value.");
static_assert(BRIGHTNESS_MODE_SENSOR == static_cast<int>(Brightness::SENSOR),
    "Brightness::SENSOR must match legacy value.");
static_assert(BRIGHTNESS_MODE_LOW_PERSISTENCE ==
    static_cast<int>(Brightness::LOW_PERSISTENCE),
    "Brightness::LOW_PERSISTENCE must match legacy value.");

Light::Light(std::map<Type, light_device_t*> &&lights)
  : mLights(std::move(lights)) {}  //将lights转换为右值,相当于mlights=lights

// Methods from ::android::hardware::light::V2_0::ILight follow.
Return<Status> Light::setLight(Type type, const LightState& state)  {
    auto it = mLights.find(type);  //找到具体light type的light_device_t *(即hal层的函数指针)

if (it == mLights.end()) {
        return Status::LIGHT_NOT_SUPPORTED;
    }

light_device_t* hwLight = it->second;

light_state_t legacyState {
        .color = state.color,
        .flashMode = static_cast<int>(state.flashMode),
        .flashOnMS = state.flashOnMs,
        .flashOffMS = state.flashOffMs,
        .brightnessMode = static_cast<int>(state.brightnessMode),
    };

int ret = hwLight->set_light(hwLight, &legacyState);

switch (ret) {
        case -ENOSYS:
            return Status::BRIGHTNESS_NOT_SUPPORTED;
        case 0:
            return Status::SUCCESS;
        default:
            return Status::UNKNOWN;
    }
}

Return<void> Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb)  {
    Type *types = new Type[mLights.size()];

int idx = 0;
    for(auto const &pair : mLights) {
        Type type = pair.first;

types[idx++] = type;
    }

{
        hidl_vec<Type> hidl_types{};
        hidl_types.setToExternal(types, mLights.size());

_hidl_cb(hidl_types);
    }

delete[] types;

return Void();
}

const static std::map<Type, const char*> kLogicalLights = {
    {Type::BACKLIGHT,     LIGHT_ID_BACKLIGHT},
    {Type::KEYBOARD,      LIGHT_ID_KEYBOARD},
    {Type::BUTTONS,       LIGHT_ID_BUTTONS},
    {Type::BATTERY,       LIGHT_ID_BATTERY},
    {Type::NOTIFICATIONS, LIGHT_ID_NOTIFICATIONS},
    {Type::ATTENTION,     LIGHT_ID_ATTENTION},
    {Type::BLUETOOTH,     LIGHT_ID_BLUETOOTH},
    {Type::WIFI,          LIGHT_ID_WIFI}
};

light_device_t* getLightDevice(const char* name) {
    light_device_tlightDevice;
    const hw_module_t* hwModule = NULL;

int ret = hw_get_module (LIGHTS_HARDWARE_MODULE_ID, &hwModule);
    if (ret == 0) {
        ret = hwModule->methods->open(hwModule, name,
            reinterpret_cast<hw_device_t**>(&lightDevice));    //将二级指针&lightDevice传给hal层
        if (ret != 0) {
            ALOGE("light_open %s %s failed: %d", LIGHTS_HARDWARE_MODULE_ID, name, ret);
        }
    } else {
        ALOGE("hw_get_module %s %s failed: %d", LIGHTS_HARDWARE_MODULE_ID, name, ret);
    }

if (ret == 0) {
        return lightDevice;
    } else {
        ALOGE("Light passthrough failed to load legacy HAL.");
        return nullptr;
    }
}

ILight* HIDL_FETCH_ILight(const char* /* name */) {  //HIDL直通式
    std::map<Type, light_device_t*> lights;

for(auto const &pair : kLogicalLights) {  //遍历所有的light type
        Type type = pair.first;
        const char* name = pair.second;

light_device_tlight = getLightDevice(name);

if (light != nullptr) {
            lights[type] = light;
        }
    }

if (lights.size() == 0) {
        // Log information, but still return new Light.
        // Some devices may not have any lights.
        ALOGI("Could not open any lights.");
    }

return new Light(std::move(lights));
}

} // namespace implementation
}  // namespace V2_0
}  // namespace light
}  // namespace hardware
}  // namespace android

HAL:

/vendor/mediatek/proprietary/hardware/liblights/Android.mk

LOCAL_PATH:= $(call my-dir)

# HAL module implemenation, not prelinked and stored in

# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so

include $(CLEAR_VARS)

LOCAL_HEADER_LIBRARIES := libhardware_headers

LOCAL_MULTILIB := both

LOCAL_MODULE_TAGS := optional

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE_RELATIVE_PATH := hw

LOCAL_SHARED_LIBRARIES := liblog

LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)

LOCAL_PROPRIETARY_MODULE := true

LOCAL_MODULE_OWNER := mtk

include $(MTK_SHARED_LIBRARY)

include $(call all-makefiles-under, $(LOCAL_PATH))

./tb8321p3_bsp/vendor/lib/hw/lights.mt6580.so

./tb8321p3_bsp/symbols/vendor/lib/hw/lights.mt6580.so

/hardware/libhardware/include/hardware/lights.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

/*
 * These light IDs correspond to logical lights, not physical.
 * So for example, if your INDICATOR light is in line with your
 * BUTTONS, it might make sense to also light the INDICATOR
 * light to a reasonable color when the BUTTONS are lit.
 */
#define LIGHT_ID_BACKLIGHT          "backlight"
#define LIGHT_ID_KEYBOARD           "keyboard"
#define LIGHT_ID_BUTTONS            "buttons"
#define LIGHT_ID_BATTERY            "battery"
#define LIGHT_ID_NOTIFICATIONS      "notifications"
#define LIGHT_ID_ATTENTION          "attention"

struct light_device_t {
    struct hw_device_t common;

/**
    * Set the provided lights to the provided values.
    *
    * Returns: 0 on succes, error code on failure.
    */
    int (*set_light)(struct light_device_t* dev,
            struct light_state_t const* state);
};

/vendor/mediatek/proprietary/hardware/liblights/lights.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

#define LOG_TAG "lights"
#include <hardware/lights.h>  //jni也include了这个(jni->hal)、hidl也include了这个(jni->hidl->hal)
... ...
/* LCD BACKLIGHT */
char const*const LCD_FILE
        = "/sys/class/leds/lcd-backlight/brightness";
... ...

/** Open a new instance of a lights device using name */
static int open_lights(const struct hw_module_t* module, char const* name,
        struct hw_device_t** device)
{
    int (*set_light)(struct light_device_t* dev,
            struct light_state_t const* state);

if (0 == strcmp(LIGHT_ID_BACKLIGHTname)) {
        set_light = set_light_backlight;
        if (access(LCD_FILE, F_OK) < 0)
            return -errno;
    }
    else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
        set_light = set_light_keyboard;
        if (access(KEYBOARD_FILE, F_OK) < 0)
            return -errno;
    }
    else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
        set_light = set_light_buttons;
        if (access(BUTTON_FILE, F_OK) < 0)
            return -errno;
    }
    else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
        set_light = set_light_battery;
        if (access(RED_LED_FILE, F_OK) < 0)
            return -errno;
        if (access(GREEN_LED_FILE, F_OK) < 0)
            return -errno;
        if (access(BLUE_LED_FILE, F_OK) < 0)
            return -errno;
    }
    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
        set_light = set_light_notifications;
        if (access(RED_LED_FILE, F_OK) < 0)
            return -errno;
        if (access(GREEN_LED_FILE, F_OK) < 0)
            return -errno;
        if (access(BLUE_LED_FILE, F_OK) < 0)
            return -errno;
    }
    else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {
        set_light = set_light_attention;
        if (access(RED_LED_FILE, F_OK) < 0)
            return -errno;
        if (access(GREEN_LED_FILE, F_OK) < 0)
            return -errno;
        if (access(BLUE_LED_FILE, F_OK) < 0)
            return -errno;
    }
    else {
        return -EINVAL;
    }

pthread_once(&g_init, init_globals);

struct light_device_t *dev = malloc(sizeof(struct light_device_t));
    if (!dev)
        return -ENOMEM;

memset(dev, 0, sizeof(*dev));

dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t*)module;
    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
    dev->set_light = set_light;

*device = (struct hw_device_t*)dev; //将jni或者hidl传进来的二级指针赋值为具体的函数指针
    return 0;
}

static struct hw_module_methods_t lights_module_methods = {
    .open =  open_lights,
};

/*
 * The lights Module
 */
struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    //.version_major = 1,
    //.version_minor = 0,
    .id = LIGHTS_HARDWARE_MODULE_ID,
    .name = "MTK lights Module",
    .author = "MediaTek",
    .methods = &lights_module_methods,
};

/vendor/mediatek/proprietary/hardware/liblights/lights.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

static int write_int(char const* path, int value)
{
    int fd;

#ifdef LIGHTS_INFO_ON
    ALOGD("write %d to %s", value, path);
#endif

fd = open(path, O_RDWR);
    ALOGD("write_int open fd=%d\n", fd);
    if (fd >= 0) {
        char buffer[20];
        int bytes = sprintf(buffer, "%d\n", value);
        int amt = write(fd, buffer, bytes);
        close(fd);
        return amt == -1 ? -errno : 0;
    } else {
        return -errno;
    }
}

static int set_light_backlight(struct light_device_t* dev,
        struct light_state_t const* state)
{
    int err = 0;
    int brightness = rgb_to_brightness(state);
    pthread_mutex_lock(&g_lock);
    g_backlight = brightness;
    err = write_int(LCD_FILE, brightness);
    if (g_haveTrackballLight) {
        handle_trackball_light_locked(dev);
    }
    pthread_mutex_unlock(&g_lock);
    return err;
}

二、通过aidl的方式:

/hardware/interfaces/light/aidl/android/hardware/light/ILights.aidl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

package android.hardware.light;

import android.hardware.light.HwLightState;
import android.hardware.light.HwLight;

/**
 * Allows controlling logical lights/indicators, mapped to LEDs in a
 * hardware-specific manner by the HAL implementation.
 */
@VintfStability
interface ILights {
    /**
     * Set light identified by id to the provided state.
     *
     * If control over an invalid light is requested, this method exists with
     * EX_UNSUPPORTED_OPERATION. Control over supported lights is done on a
     * device-specific best-effort basis and unsupported sub-features will not
     * be reported.
     *
     * @param id ID of logical light to set as returned by getLights()
     * @param state describes what the light should look like.
     */
    void setLightState(in int id, in HwLightState state);

/**
     * Discover what lights are supported by the HAL implementation.
     *
     * @return List of available lights
     */
    HwLight[] getLights();
}

/vendor/mediatek/proprietary/hardware/liblights/aidl/default/Android.bp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

cc_binary {
    name: "android.hardware.lights-service.mediatek",
    relative_install_path: "hw",
    init_rc: ["lights-mtk-default.rc"],
    vintf_fragments: ["lights-mtk-default.xml"],
    vendor: true,
    shared_libs: [
        "libbase",
        "libutils",
        "liblog",
        "libbinder_ndk",
        "android.hardware.light-ndk_platform",
        "libhardware",
        "libhardware_legacy",
    ],
    srcs: [
        "Lights.cpp",
        "main.cpp",  #ABinderProcess_joinThreadPool();
    ],
}

androidgroup04@androidgroup04:~/disk00/Isaac/MT8168_alps-mp-r0.mp5/alps/out/target/product/tb8168p1_64_bsp$ find -name "*android.hardware.lights-service.mediatek*"

./vendor/bin/hw/android.hardware.lights-service.mediatek

./obj/EXECUTABLES/android.hardware.lights-service.mediatek_intermediates

./obj/EXECUTABLES/android.hardware.lights-service.mediatek_intermediates/android.hardware.lights-service.mediatek

./obj/PACKAGING/vendor_target_files_intermediates/vnd_tb8168p1_64_bsp-vendor_target_files-mp5V4381/VENDOR/bin/hw/android.hardware.lights-service.mediatek

./symbols/vendor/bin/hw/android.hardware.lights-service.mediatek

/vendor/mediatek/proprietary/hardware/liblights/aidl/default/Lights.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

#include "Lights.h"

namespace aidl {
namespace android {
namespace hardware {
namespace light {

using ::aidl::android::hardware::light::BnLights;
using ::aidl::android::hardware::light::HwLight;
using ::aidl::android::hardware::light::HwLightState;
using ::aidl::android::hardware::light::ILights;
using ::aidl::android::hardware::light::LightType;
using ::aidl::android::hardware::light::FlashMode;
... ...
ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {

#ifdef LIGHTS_INFO_ON
    ALOGD("Lights setting state for id=%d, color=%0x\n",
            id, state.color);
#endif
    if (!(0 <= id && id < availableLights.size())) {
        ALOGI("Lights id %d does not exist.", id);
        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
      }

//int const color = rgbToBrightness(state.color);
    HwLight const* light = &(availableLights[id]);

int ret = 0;

switch (light->type) {
        case LightType::BACKLIGHT:
            ret = set_light_backlight(light, &state);
            break;
        case LightType::KEYBOARD:
            ret = set_light_keyboard(light, &state);
            break;
        case LightType::BUTTONS:
            ret = set_light_buttons(light, &state);
            break;
        case LightType::BATTERY:
            ret = set_light_battery(light, &state);
            break;
        case LightType::NOTIFICATIONS:
            ret = set_light_notifications(light, &state);
            break;
        case LightType::ATTENTION:
            ret = set_light_attention(light, &state);
            break;
        default:
            return ndk::ScopedAStatus::fromServiceSpecificError(EX_UNSUPPORTED_OPERATION);
    }
    switch (ret) {
        case -ENXIO:
            ALOGI("Lights id %d return %d.", id, ret);
        case 0:
            return ndk::ScopedAStatus::ok();
        default:
            ALOGI("Lights id %d return %d.", id, ret);
            return ndk::ScopedAStatus::fromServiceSpecificError(EX_UNSUPPORTED_OPERATION);
    }
}

}  // namespace light
}  // namespace hardware
}  // namespace android
}  // namespace aidl

/vendor/mediatek/proprietary/hardware/liblights/aidl/default/Lights.h

1
2
3

/* LCD BACKLIGHT */
char const*const LCD_FILE
        = "/sys/class/leds/lcd-backlight/brightness";

/vendor/mediatek/proprietary/hardware/liblights/aidl/default/Lights.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

static int
set_light_backlight(HwLight const* light, HwLightState const* state)
{
    if(!light) {
         return -1;
    }

int err = 0;
    int brightness = rgb_to_brightness(state);
    if (!device_exists(LCD_FILE)) {
        return -ENXIO;
    }
#ifdef LIGHTS_INFO_ON
    ALOGD("set_light_backlight, level=%d, onMS=%d, offMS=%d\n",
        brightness, state->flashOnMs, state->flashOffMs);
#endif

pthread_mutex_lock(&g_lock);
    g_backlight = brightness;
    err = write_int(LCD_FILEbrightness);
    if (g_haveTrackballLight) {
        handle_trackball_light_locked(light, state);
    }
    pthread_mutex_unlock(&g_lock);
    return err;
}

/vendor/mediatek/proprietary/hardware/liblights/aidl/default/Lights.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

static int write_int(char const* path, int value)
{
    int fd = -1, ret = 0;

#ifdef LIGHTS_DBG_ON
    ALOGD("write %d to %s", value, path);
#endif

fd = open(path, O_RDWR);
    if (fd >= 0) {
        char buffer[20];
        int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);  //将背光亮度格式化为字符串保存在buffer,返回字符串长度
        if (bytes >= sizeof(buffer)) {
            ret = -EINVAL;
            ALOGE("write error1 %d to %s, ret=%d", value, path, ret);
        } else {
            int amt = write(fdbuffer, bytes);  //往节点写数据
            ret = (amt == -1 ? -errno : 0);
        }
        close(fd);
        fd = -1;
    } else {
        ret = -errno;
        ALOGE("write %d to %s, result: %d", value, path, ret);
    }
    ALOGD("write %d to %s, result: %d", value, path, ret);
    return ret;
}

==================================================================

09.mtk背光流程相关推荐

  1. mtk LK流程简介

    mtk LK流程简介 一.LK简介 Lk的主要功能: 1.初始化硬件模块,比如时钟,中断,UART,USB,LCD,PMIC,eMMC等.打开MMU,使能I/D-cache,加速lk执行,显示logo ...

  2. 10.sprd背光流程

    Android 背光流程小结 现在使用aidl方式: /hardware/interfaces/light/aidl/android/hardware/light/ILights.aidl 1 2 3 ...

  3. Android原生调节屏幕背光流程

    Android 5.1调节背光流程 版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. https://mp.csdn.net/mdeditor/ ...

  4. mtk preloader流程简介

    ## mtk preloader流程简介 **一.preloader流程简介 1.启动流程 (1)设备上电起来后,跳转到Boot ROM(不是flash)中的bootcode中执行把pre-loade ...

  5. Android7.1 控制背光流程

    背光调节通信图,如下 如论上层哪里控制背光,上图部分是共用的流程,每次设置一个新的背光值,都会从上一个背光值开始,在RampAnimator.java以计算出的步长调整背光到目标背光值,因此是一个渐变 ...

  6. A4. MTK开机流程

    preloader流程: 路径: vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6761/src/core/ ...

  7. 【转载】【非常好】MTK 电池流程.c

    /* 概念: ZCV:开路电压OCV: 开路电压VC:闭路电压CAR:库伦计DOD: 放电深度,100-DOD 即电容容量Cmax/Qmax: 电池容量相关文件关系:Battery_common.c ...

  8. (转)MTK softkey流程 必看

    SetKeyHandler()的流程 设置按键处理的函数使用SetKeyHandler() 这个函数的大概实现如下(精简版哈): void SetKeyHandler(FuncPtr funcPtr, ...

  9. android 自动背光闪烁,Android 背光流程小结

    android背光控制小结,从上到下: ----android---- DisplayPowerController.java--> DisplayPowerState.java:SCREEN_ ...

  10. ELT MTK CallLog流程分析 MO/MT

    首先讲主动发起通话流程 MO 2G,2G通话联通已经不支持了. MO 3G Step 1: CM service request 发起通话服务请求 Step 2: RRC connect reques ...

最新文章

  1. mtr命令详解诊断网络路由
  2. W - Pasha and Phone CodeForces - 595B (收益颇丰的数学题
  3. 光纤会在将来完全取代铜缆吗?
  4. c语言循环结构程序设计视频,第13讲:循环结构程序设计1
  5. 程序员的未来真的一片阴霾吗,大厂女程序员从未摆脱焦虑
  6. PCB设计中的问题整理
  7. OpenCV Stitching 工程搭建
  8. 两台邮件服务器共用一个公网地址,两个不同域邮件服务器的互通
  9. Android-标题状态栏的隐藏
  10. 【AI面试题】GBDT原理、如何用于分类、常用损失函数
  11. 【洛谷】P1052 过河(状压dp)
  12. 设计模式(三)模版方法(行为型)
  13. C++基础::为什么不能cout一个string?
  14. shopnum1商城系统
  15. C#.net的常用函数列表
  16. 网络游戏加速器软件市场现状研究分析-
  17. 天然气故障代码大全_天然气发动机故障代码表(20130101)
  18. 鼎捷软件ERP,MES等系统构筑制造企业信息化系统
  19. [转载] 网页制作常用英语标示
  20. 防盗定位追踪,电动车安全管理“神器”装一个?

热门文章

  1. 什么蓝牙耳机音质好?盘点四款HIFI音质蓝牙耳机排行榜
  2. 符冉迪 计算机 培训,一种卫星云图的二次聚类分割方法专利_专利申请于2012-11-30_专利查询 - 天眼查...
  3. excel单元格内换行的方法
  4. 免费 whois 查询 API
  5. ChineseLunisolarCalendar 农历日期
  6. MimeType对照表
  7. 天线开路短路检测原理_LEA-5S的天线开路检测问题
  8. mysql校对集_MySQL校对集问题的教程
  9. 数据库课程设计矿大_中国矿业大学选课系统
  10. Altium Designer15安装破解教程