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 class LightHal {
43 private:
44 static sp<ILight> sLight;
45 static bool sLightInit;
46
LightHal()47 LightHal() {}
48
49 public:
disassociate()50 static void disassociate() {
51 sLightInit = false;
52 sLight = nullptr;
53 }
54
associate()55 static sp<ILight> associate() {
56 if ((sLight == nullptr && !sLightInit) ||
57 (sLight != nullptr && !sLight->ping().isOk())) {
58 // will return the hal if it exists the first time.
59 sLight = ILight::getService();
60 sLightInit = true;
61
62 if (sLight == nullptr) {
63 ALOGE("Unable to get ILight interface.");
64 }
65 }
66
67 return sLight;
68 }
69 };
70
71 sp<ILight> LightHal::sLight = nullptr;
72 bool LightHal::sLightInit = false;
73
validate(jint light,jint flash,jint brightness)74 static bool validate(jint light, jint flash, jint brightness) {
75 bool valid = true;
76
77 if (light < 0 || light >= static_cast<jint>(Type::COUNT)) {
78 ALOGE("Invalid light parameter %d.", light);
79 valid = false;
80 }
81
82 if (flash != static_cast<jint>(Flash::NONE) &&
83 flash != static_cast<jint>(Flash::TIMED) &&
84 flash != static_cast<jint>(Flash::HARDWARE)) {
85 ALOGE("Invalid flash parameter %d.", flash);
86 valid = false;
87 }
88
89 if (brightness != static_cast<jint>(Brightness::USER) &&
90 brightness != static_cast<jint>(Brightness::SENSOR) &&
91 brightness != static_cast<jint>(Brightness::LOW_PERSISTENCE)) {
92 ALOGE("Invalid brightness parameter %d.", brightness);
93 valid = false;
94 }
95
96 if (brightness == static_cast<jint>(Brightness::LOW_PERSISTENCE) &&
97 light != static_cast<jint>(Type::BACKLIGHT)) {
98 ALOGE("Cannot set low-persistence mode for non-backlight device.");
99 valid = false;
100 }
101
102 return valid;
103 }
104
constructState(jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode)105 static LightState constructState(
106 jint colorARGB,
107 jint flashMode,
108 jint onMS,
109 jint offMS,
110 jint brightnessMode){
111 Flash flash = static_cast<Flash>(flashMode);
112 Brightness brightness = static_cast<Brightness>(brightnessMode);
113
114 LightState state{};
115
116 if (brightness == Brightness::LOW_PERSISTENCE) {
117 state.flashMode = Flash::NONE;
118 } else {
119 // Only set non-brightness settings when not in low-persistence mode
120 state.flashMode = flash;
121 state.flashOnMs = onMS;
122 state.flashOffMs = offMS;
123 }
124
125 state.color = colorARGB;
126 state.brightnessMode = brightness;
127
128 return state;
129 }
130
processReturn(const Return<Status> & ret,Type type,const LightState & state)131 static void processReturn(
132 const Return<Status> &ret,
133 Type type,
134 const LightState &state) {
135 if (!ret.isOk()) {
136 ALOGE("Failed to issue set light command.");
137 LightHal::disassociate();
138 return;
139 }
140
141 switch (static_cast<Status>(ret)) {
142 case Status::SUCCESS:
143 break;
144 case Status::LIGHT_NOT_SUPPORTED:
145 ALOGE("Light requested not available on this device. %d", type);
146 break;
147 case Status::BRIGHTNESS_NOT_SUPPORTED:
148 ALOGE("Brightness parameter not supported on this device: %d",
149 state.brightnessMode);
150 break;
151 case Status::UNKNOWN:
152 default:
153 ALOGE("Unknown error setting light.");
154 }
155 }
156
setLight_native(JNIEnv *,jobject,jint light,jint colorARGB,jint flashMode,jint onMS,jint offMS,jint brightnessMode)157 static void setLight_native(
158 JNIEnv* /* env */,
159 jobject /* clazz */,
160 jint light,
161 jint colorARGB,
162 jint flashMode,
163 jint onMS,
164 jint offMS,
165 jint brightnessMode) {
166
167 if (!validate(light, flashMode, brightnessMode)) {
168 return;
169 }
170
171 sp<ILight> hal = LightHal::associate();
172
173 if (hal == nullptr) {
174 return;
175 }
176
177 Type type = static_cast<Type>(light);
178 LightState state = constructState(
179 colorARGB, flashMode, onMS, offMS, brightnessMode);
180
181 {
182 android::base::Timer t;
183 Return<Status> ret = hal->setLight(type, state);
184 processReturn(ret, type, state);
185 if (t.duration() > 50ms) ALOGD("Excessive delay setting light");
186 }
187 }
188
189 static const JNINativeMethod method_table[] = {
190 { "setLight_native", "(IIIIII)V", (void*)setLight_native },
191 };
192
register_android_server_LightsService(JNIEnv * env)193 int register_android_server_LightsService(JNIEnv *env) {
194 return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
195 method_table, NELEM(method_table));
196 }
197
198 };
199