1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "LightsService"
18
19#include "jni.h"
20#include "JNIHelp.h"
21#include "android_runtime/AndroidRuntime.h"
22
23#include <utils/misc.h>
24#include <utils/Log.h>
25#include <hardware/hardware.h>
26#include <hardware/lights.h>
27
28#include <stdio.h>
29
30namespace android
31{
32
33// These values must correspond with the LIGHT_ID constants in
34// LightsService.java
35enum {
36    LIGHT_INDEX_BACKLIGHT = 0,
37    LIGHT_INDEX_KEYBOARD = 1,
38    LIGHT_INDEX_BUTTONS = 2,
39    LIGHT_INDEX_BATTERY = 3,
40    LIGHT_INDEX_NOTIFICATIONS = 4,
41    LIGHT_INDEX_ATTENTION = 5,
42    LIGHT_INDEX_BLUETOOTH = 6,
43    LIGHT_INDEX_WIFI = 7,
44    LIGHT_COUNT
45};
46
47struct Devices {
48    light_device_t* lights[LIGHT_COUNT];
49};
50
51static light_device_t* get_device(hw_module_t* module, char const* name)
52{
53    int err;
54    hw_device_t* device;
55    err = module->methods->open(module, name, &device);
56    if (err == 0) {
57        return (light_device_t*)device;
58    } else {
59        return NULL;
60    }
61}
62
63static jlong init_native(JNIEnv* /* env */, jobject /* clazz */)
64{
65    int err;
66    hw_module_t* module;
67    Devices* devices;
68
69    devices = (Devices*)malloc(sizeof(Devices));
70
71    err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
72    if (err == 0) {
73        devices->lights[LIGHT_INDEX_BACKLIGHT]
74                = get_device(module, LIGHT_ID_BACKLIGHT);
75        devices->lights[LIGHT_INDEX_KEYBOARD]
76                = get_device(module, LIGHT_ID_KEYBOARD);
77        devices->lights[LIGHT_INDEX_BUTTONS]
78                = get_device(module, LIGHT_ID_BUTTONS);
79        devices->lights[LIGHT_INDEX_BATTERY]
80                = get_device(module, LIGHT_ID_BATTERY);
81        devices->lights[LIGHT_INDEX_NOTIFICATIONS]
82                = get_device(module, LIGHT_ID_NOTIFICATIONS);
83        devices->lights[LIGHT_INDEX_ATTENTION]
84                = get_device(module, LIGHT_ID_ATTENTION);
85        devices->lights[LIGHT_INDEX_BLUETOOTH]
86                = get_device(module, LIGHT_ID_BLUETOOTH);
87        devices->lights[LIGHT_INDEX_WIFI]
88                = get_device(module, LIGHT_ID_WIFI);
89    } else {
90        memset(devices, 0, sizeof(Devices));
91    }
92
93    return (jlong)devices;
94}
95
96static void finalize_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr)
97{
98    Devices* devices = (Devices*)ptr;
99    if (devices == NULL) {
100        return;
101    }
102
103    free(devices);
104}
105
106static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
107        jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
108{
109    Devices* devices = (Devices*)ptr;
110    light_state_t state;
111
112    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
113        return ;
114    }
115
116    uint32_t version = devices->lights[light]->common.version;
117
118    memset(&state, 0, sizeof(light_state_t));
119
120    if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
121        if (light != LIGHT_INDEX_BACKLIGHT) {
122            ALOGE("Cannot set low-persistence mode for non-backlight device.");
123            return;
124        }
125        if (version < LIGHTS_DEVICE_API_VERSION_2_0) {
126            // HAL impl has not been upgraded to support this.
127            return;
128        }
129    } else {
130        // Only set non-brightness settings when not in low-persistence mode
131        state.color = colorARGB;
132        state.flashMode = flashMode;
133        state.flashOnMS = onMS;
134        state.flashOffMS = offMS;
135    }
136
137    state.brightnessMode = brightnessMode;
138
139    {
140        ALOGD_IF_SLOW(50, "Excessive delay setting light");
141        devices->lights[light]->set_light(devices->lights[light], &state);
142    }
143}
144
145static const JNINativeMethod method_table[] = {
146    { "init_native", "()J", (void*)init_native },
147    { "finalize_native", "(J)V", (void*)finalize_native },
148    { "setLight_native", "(JIIIIII)V", (void*)setLight_native },
149};
150
151int register_android_server_LightsService(JNIEnv *env)
152{
153    return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
154            method_table, NELEM(method_table));
155}
156
157};
158