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 <nativehelper/JNIHelp.h>
21 #include "android_runtime/AndroidRuntime.h"
22
23 #include <android/hardware/light/2.0/ILight.h>
24 #include <android/hardware/light/2.0/types.h>
25 #include <android-base/chrono_utils.h>
26 #include <utils/misc.h>
27 #include <utils/Log.h>
28 #include <map>
29 #include <stdio.h>
30
31 namespace android {
32
33 using Brightness = ::android::hardware::light::V2_0::Brightness;
34 using Flash = ::android::hardware::light::V2_0::Flash;
35 using ILight = ::android::hardware::light::V2_0::ILight;
36 using LightState = ::android::hardware::light::V2_0::LightState;
37 using Status = ::android::hardware::light::V2_0::Status;
38 using Type = ::android::hardware::light::V2_0::Type;
39 template<typename T>
40 using Return = ::android::hardware::Return<T>;
41
42 static bool sLightSupported = true;
43
validate(jint light,jint flash,jint brightness)44 static bool validate(jint light, jint flash, jint brightness) {
45 bool valid = true;
46
47 if (light < 0 || light >= static_cast<jint>(Type::COUNT)) {
48 ALOGE("Invalid light parameter %d.", light);
49 valid = false;
50 }
51
52 if (flash != static_cast<jint>(Flash::NONE) &&
53 flash != static_cast<jint>(Flash::TIMED) &&
54 flash != static_cast<jint>(Flash::HARDWARE)) {
55 ALOGE("Invalid flash parameter %d.", flash);
56 valid = false;
57 }
58
59 if (brightness != static_cast<jint>(Brightness::USER) &&
60 brightness != static_cast<jint>(Brightness::SENSOR) &&
61 brightness != static_cast<jint>(Brightness::LOW_PERSISTENCE)) {
62 ALOGE("Invalid brightness parameter %d.", brightness);
63 valid = false;
64 }
65
66 if (brightness == static_cast<jint>(Brightness::LOW_PERSISTENCE) &&
67 light != static_cast<jint>(Type::BACKLIGHT)) {
68 ALOGE("Cannot set low-persistence mode for non-backlight device.");
69 valid = false;
70 }
71
72 return valid;
73 }
74
constructState(jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode)75 static LightState constructState(
76 jint colorARGB,
77 jint flashMode,
78 jint onMS,
79 jint offMS,
80 jint brightnessMode){
81 Flash flash = static_cast<Flash>(flashMode);
82 Brightness brightness = static_cast<Brightness>(brightnessMode);
83
84 LightState state{};
85
86 if (brightness == Brightness::LOW_PERSISTENCE) {
87 state.flashMode = Flash::NONE;
88 } else {
89 // Only set non-brightness settings when not in low-persistence mode
90 state.flashMode = flash;
91 state.flashOnMs = onMS;
92 state.flashOffMs = offMS;
93 }
94
95 state.color = colorARGB;
96 state.brightnessMode = brightness;
97
98 return state;
99 }
100
processReturn(const Return<Status> & ret,Type type,const LightState & state)101 static void processReturn(
102 const Return<Status> &ret,
103 Type type,
104 const LightState &state) {
105 if (!ret.isOk()) {
106 ALOGE("Failed to issue set light command.");
107 return;
108 }
109
110 switch (static_cast<Status>(ret)) {
111 case Status::SUCCESS:
112 break;
113 case Status::LIGHT_NOT_SUPPORTED:
114 ALOGE("Light requested not available on this device. %d", type);
115 break;
116 case Status::BRIGHTNESS_NOT_SUPPORTED:
117 ALOGE("Brightness parameter not supported on this device: %d",
118 state.brightnessMode);
119 break;
120 case Status::UNKNOWN:
121 default:
122 ALOGE("Unknown error setting light.");
123 }
124 }
125
setLight_native(JNIEnv *,jobject,jint light,jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode)126 static void setLight_native(
127 JNIEnv* /* env */,
128 jobject /* clazz */,
129 jint light,
130 jint colorARGB,
131 jint flashMode,
132 jint onMS,
133 jint offMS,
134 jint brightnessMode) {
135
136 if (!sLightSupported) {
137 return;
138 }
139
140 if (!validate(light, flashMode, brightnessMode)) {
141 return;
142 }
143
144 Type type = static_cast<Type>(light);
145 LightState state = constructState(
146 colorARGB, flashMode, onMS, offMS, brightnessMode);
147
148 {
149 android::base::Timer t;
150 sp<ILight> hal = ILight::getService();
151 if (hal == nullptr) {
152 sLightSupported = false;
153 return;
154 }
155 Return<Status> ret = hal->setLight(type, state);
156 processReturn(ret, type, state);
157 if (t.duration() > 50ms) ALOGD("Excessive delay setting light");
158 }
159 }
160
161 static const JNINativeMethod method_table[] = {
162 { "setLight_native", "(IIIIII)V", (void*)setLight_native },
163 };
164
register_android_server_LightsService(JNIEnv * env)165 int register_android_server_LightsService(JNIEnv *env) {
166 return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
167 method_table, NELEM(method_table));
168 }
169
170 };
171