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