1.[Lights]-(Android 8.1 lights分析)

安卓充电灯更新逻辑:
1.灯相关变量定义:
frameworks/base/core/res/res/values/symbols.xml

  <java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
  <java-symbol type="integer" name="config_notificationsBatteryLedOff" />
  <java-symbol type="integer" name="config_notificationsBatteryLedOn" />
  <java-symbol type="integer" name="config_notificationsBatteryLowARGB" />
  <java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />

2.定义值
frameworks/base/core/res/res/values/config.xml

  <!-- Default color for notification LED. -->
    <color name="config_defaultNotificationColor">#ffffffff</color>

    <!-- Default LED on time for notification LED in milliseconds. -->
    <integer name="config_defaultNotificationLedOn">500</integer>

    <!-- Default LED off time for notification LED in milliseconds. -->
    <integer name="config_defaultNotificationLedOff">2000</integer>

    <!-- Default value for led color when battery is low on charge -->
    <integer name="config_notificationsBatteryLowARGB">0xFFFF0000</integer>

    <!-- Default value for led color when battery is medium charged -->
    <integer name="config_notificationsBatteryMediumARGB">0xFFFFFF00</integer>

    <!-- Default value for led color when battery is fully charged -->
    <integer name="config_notificationsBatteryFullARGB">0xFF00FF00</integer>

3.充电灯状态更新逻辑:
frameworks/base/services/java/com/android/server/BatteryService.java

    private final class Led {
        private final LightsService.Light mBatteryLight;

        private final int mBatteryLowARGB;
        private final int mBatteryMediumARGB;
        private final int mBatteryFullARGB;
        private final int mBatteryLedOn;
        private final int mBatteryLedOff;

        public Led(Context context, LightsService lights) {
            mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);

            mBatteryLowARGB = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryLowARGB);
            mBatteryMediumARGB = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
            mBatteryFullARGB = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryFullARGB);
            mBatteryLedOn = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryLedOn);
            mBatteryLedOff = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryLedOff);
        }
        /**
         * Synchronize on BatteryService.
         */
        public void updateLightsLocked() {
            final int level = mBatteryProps.batteryLevel;
            final int status = mBatteryProps.batteryStatus;
            if (level < mLowBatteryWarningLevel) {
                if (status == BatteryManager.BATTERY_STATUS_CHARGING) { //当处于低电量时,调用setColor()
                    // Solid red when battery is charging
                    mBatteryLight.setColor(mBatteryLowARGB);
                } else {
                    // Flash red when battery is low and not charging
                    mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED,
                            mBatteryLedOn, mBatteryLedOff);
                }
            } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
                    || status == BatteryManager.BATTERY_STATUS_FULL) { 
                if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) { //电量大于百分90或状态为FULL时
                    // Solid green when full or charging and nearly full
                    mBatteryLight.setColor(mBatteryFullARGB);
                } else { //电量小于90 且 非低电量时。
                    // Solid orange when charging and halfway full
                    mBatteryLight.setColor(mBatteryMediumARGB);
                }
            } else {
                // No lights if not charging and not low
                mBatteryLight.turnOff();
            }
        }

4.安卓lightservice灯相关的操作接口:
frameworks/base/services/java/com/android/server/LightsService.java

        public void setBrightness(int brightness) {
            setBrightness(brightness, BRIGHTNESS_MODE_USER);
        }

        public void setBrightness(int brightness, int brightnessMode) {
            synchronized (this) {
                int color = brightness & 0x000000ff;
                color = 0xff000000 | (color << 16) | (color << 8) | color;
                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
            }
        }

        public void setColor(int color) {
            synchronized (this) {
                //setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
              setLightLocked(color, LIGHT_FLASH_TIMED, 500, 500, BRIGHTNESS_MODE_USER);
            }
        }

        public void setFlashing(int color, int mode, int onMS, int offMS) {
            synchronized (this) {
                setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
            }
        }


        public void pulse() {
            pulse(0x00ffffff, 7);
        }

        public void pulse(int color, int onMS) {
            synchronized (this) {
                if (mColor == 0 && !mFlashing) {
                    setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
                    mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
                }
            }
        }

        public void turnOff() {
            synchronized (this) {
                setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
            }
        }

        private void stopFlashing() {
            synchronized (this) {
                setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);
            }
        }

        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
            if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
                if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
                        + Integer.toHexString(color));
                mColor = color;
                mMode = mode;
                mOnMS = onMS;
                mOffMS = offMS;
                setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
            }
        }

lightsService 注册:
路径:frameworks/base/services/java/com/android/server/SystemServer.java

        // Manages LEDs and display backlight so we need it to bring up the display.
        traceBeginAndSlog("StartLightsService");
        mSystemServiceManager.startService(LightsService.class);
        traceEnd();

lights服务代码
frameworks/base/services/core/java/com/android/server/lights/LightsService.java

在这个服务中,对led灯所有操作都是通过下面这个接口实现的:
    static native void setLight_native(int light, int color, int mode,
            int onMS, int offMS, int brightnessMode);
}

lights jni层代码:
主要作用是在O版及之后衔接hidl层和注册本地方法到这个类:com/android/server/lights/LightsService
路径:frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp

static void setLight_native(
        JNIEnv* /* env */,
        jobject /* clazz */,
        jint light,
        jint colorARGB,
        jint flashMode,
        jint onMS,
        jint offMS,
        jint brightnessMode) {

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

    sp<ILight> hal = LightHal::associate();

    if (hal == nullptr) {
        return;
    }

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

    {
        android::base::Timer t;
        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 层(分为直通式:兼容之前的旧框架,直接使用dlopen和binder式:还未了解):
-> 直通式:安卓O及之后版本,不在是直接在jni处调用hw_get_module直接jni处调用,而是在hidl出调用,
->bingder式:还未了解
路径:/hardware/interfaces/light/

/here to add a lights interface by zwl 
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_t* lightDevice;
    const hw_module_t* hwModule = NULL;

    int ret = hw_get_module (LIGHTS_HARDWARE_MODULE_ID, &hwModule); //call the .so //dlopen直通式
    if (ret == 0) {
        ret = hwModule->methods->open(hwModule, name,
            reinterpret_cast<hw_device_t**>(&lightDevice));
        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 */) {
    std::map<Type, light_device_t*> lights;

    for(auto const &pair : kLogicalLights) {
        Type type = pair.first;
        const char* name = pair.second;

        light_device_t* light = 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));
}

vendor层:
实现HAL_MODULE_INFO_SYM符号so库,和实现调用方法。
路径:vendor/mediatek/proprietary/hardware/liblights

/** 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_BACKLIGHT, name)) {
        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;
    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,
};

kernel层:
kernel-4.9/drivers/misc/mediatek/leds

猜你喜欢

转载自blog.csdn.net/qq_16919359/article/details/102931362
今日推荐